diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt
index b8112e446..a866784b4 100644
--- a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt
+++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt
@@ -1,2 +1,3 @@
ADD_SUBDIRECTORY(example)
+ADD_SUBDIRECTORY(ovqt_sheet_builder)
ADD_SUBDIRECTORY(log)
diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/CMakeLists.txt
new file mode 100644
index 000000000..5a9bc2913
--- /dev/null
+++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/CMakeLists.txt
@@ -0,0 +1,32 @@
+INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${LIBXML2_INCLUDE_DIR}
+ ${QT_INCLUDES})
+
+FILE(GLOB SRC *.cpp *.h)
+SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h)
+
+SET(OVQT_PLUG_SHEET_BUILDER_HDR sheetbuilderconfgdialog.h sheetbuilderdialog.h ovqt_sheet_builder.h)
+
+SET(QT_USE_QTGUI TRUE)
+SET(QT_USE_QTOPENGL TRUE)
+
+QT4_WRAP_CPP(OVQT_PLUG_SHEET_BUILDER_MOC_SRC ${OVQT_PLUG_SHEET_BUILDER_HDR})
+
+SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_SHEET_BUILDER_MOC_SRC})
+SOURCE_GROUP("Sheet builder Plugin" FILES ${SRC})
+SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC})
+
+ADD_LIBRARY(ovqt_plugin_sheet_builder SHARED ${SRC} ${OVQT_PLUG_SHEET_BUILDER_MOC_SRC} ${OVQT_EXT_SYS_SRC})
+
+TARGET_LINK_LIBRARIES(ovqt_plugin_sheet_builder nelmisc ${QT_LIBRARIES})
+
+NL_DEFAULT_PROPS(ovqt_plugin_sheet_builder "NeL, Tools, 3D: Object Viewer Qt Plugin: Sheet builder")
+NL_ADD_RUNTIME_FLAGS(ovqt_plugin_sheet_builder)
+NL_ADD_LIB_SUFFIX(ovqt_plugin_sheet_builder)
+
+ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS})
+
+INSTALL(TARGETS ovqt_plugin_sheet_builder LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d)
diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp
new file mode 100644
index 000000000..d557c6001
--- /dev/null
+++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp
@@ -0,0 +1,107 @@
+// NeL - MMORPG Framework
+// Copyright (C) 2010 Winch Gate Property Limited
+//
+// 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 .
+
+#include "ovqt_sheet_builder.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../../extension_system/iplugin_spec.h"
+
+#include "nel/misc/debug.h"
+#include "sheetbuilderdialog.h"
+#include "sheetbuilderconfgdialog.h"
+
+using namespace Plugin;
+
+bool SheetBuilderPlugin::initialize(NLQT::IPluginManager *pluginManager, QString *errorString)
+{
+ Q_UNUSED(errorString);
+ _plugMan = pluginManager;
+ return true;
+}
+
+void SheetBuilderPlugin::extensionsInitialized()
+{
+ QMenu *toolsMenu = qobject_cast(objectByName("ovqt.Menu.Tools"));
+ nlassert(toolsMenu);
+
+ toolsMenu->addSeparator();
+
+ QAction *actBuilder = toolsMenu->addAction("Sheet builder");
+ connect(actBuilder, SIGNAL(triggered()), this, SLOT(execBuilderDialog()));
+}
+
+void SheetBuilderPlugin::execBuilderDialog()
+{
+ QMainWindow *wnd = qobject_cast(objectByName("CMainWindow"));
+ nlassert(wnd);
+
+ SheetBuilderDialog dlg(wnd);
+ dlg.exec();
+}
+
+void SheetBuilderPlugin::setNelContext(NLMISC::INelContext *nelContext)
+{
+#ifdef NL_OS_WINDOWS
+ // Ensure that a context doesn't exist yet.
+ // This only applies to platforms without PIC, e.g. Windows.
+ nlassert(!NLMISC::INelContext::isContextInitialised());
+#endif // NL_OS_WINDOWS
+ _LibContext = new NLMISC::CLibraryContext(*nelContext);
+}
+
+QString SheetBuilderPlugin::name() const
+{
+ return "Sheet builder";
+}
+
+QString SheetBuilderPlugin::version() const
+{
+ return "1.0";
+}
+
+QString SheetBuilderPlugin::vendor() const
+{
+ return "kharvd";
+}
+
+QString SheetBuilderPlugin::description() const
+{
+ return "make_sheet_id equivalent";
+}
+
+QObject* SheetBuilderPlugin::objectByName(const QString &name) const
+{
+ Q_FOREACH (QObject *qobj, _plugMan->allObjects())
+ if (qobj->objectName() == name)
+ return qobj;
+ return 0;
+}
+
+NLQT::IPluginSpec *SheetBuilderPlugin::pluginByName(const QString &name) const
+{
+ Q_FOREACH (NLQT::IPluginSpec *spec, _plugMan->plugins())
+ if (spec->name() == name)
+ return spec;
+ return 0;
+}
+
+Q_EXPORT_PLUGIN(SheetBuilderPlugin)
diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h
new file mode 100644
index 000000000..dc2b18c30
--- /dev/null
+++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h
@@ -0,0 +1,72 @@
+// NeL - MMORPG Framework
+// Copyright (C) 2010 Winch Gate Property Limited
+//
+// 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 PLUGIN_H
+#define PLUGIN_H
+
+#include "../../extension_system/iplugin.h"
+
+#include "nel/misc/app_context.h"
+
+#include
+
+namespace NLMISC
+{
+ class CLibraryContext;
+}
+
+namespace NLQT
+{
+ class IPluginSpec;
+}
+
+namespace Plugin
+{
+
+ class SheetBuilderPlugin : public QObject, public NLQT::IPlugin
+ {
+ Q_OBJECT
+ Q_INTERFACES(NLQT::IPlugin)
+ public:
+ bool initialize(NLQT::IPluginManager *pluginManager, QString *errorString);
+ void extensionsInitialized();
+
+ void setNelContext(NLMISC::INelContext *nelContext);
+
+ QString name() const;
+ QString version() const;
+ QString vendor() const;
+ QString description() const;
+
+ QObject *objectByName(const QString &name) const;
+ NLQT::IPluginSpec *pluginByName(const QString &name) const;
+
+ void buildSheet(bool clean);
+
+ private Q_SLOTS:
+ void execBuilderDialog();
+
+ protected:
+ NLMISC::CLibraryContext *_LibContext;
+
+ private:
+ NLQT::IPluginManager *_plugMan;
+
+ };
+
+} // namespace Plugin
+
+#endif // PLUGIN_H
diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro
new file mode 100644
index 000000000..02926cb95
--- /dev/null
+++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro
@@ -0,0 +1,17 @@
+TEMPLATE = lib
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+CONFIG += plugin
+# Input
+HEADERS += ovqt_sheet_builder.h \
+ ../../extension_system/iplugin.h \
+ ../../extension_system/iplugin_manager.h \
+ ../../extension_system/plugin_spec.h \
+ sheetbuilderdialog.h \
+ sheetbuilder.h \
+ sheetbuilderconfgdialog.h
+SOURCES += ovqt_sheet_builder.cpp \
+ ../../extension_system/plugin_spec.cpp \
+ sheetbuilderdialog.cpp \
+ sheetbuilderconfgdialog.cpp
diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilder.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilder.h
new file mode 100644
index 000000000..4d23007fe
--- /dev/null
+++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilder.h
@@ -0,0 +1,343 @@
+// NeL - MMORPG Framework
+// Copyright (C) 2010 Winch Gate Property Limited
+//
+// 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 SHEETBUILDER_H
+#define SHEETBUILDER_H
+
+// misc
+#include
+#include
+#include
+#include
+
+// std
+#include
+#include
+
+#include
+
+
+using namespace NLMISC;
+using namespace std;
+
+#ifndef NL_MK_SH_ID_CFG
+#define NL_MK_SH_ID_CFG "."
+#endif // NL_MK_SH_ID_CFG
+
+/**
+ * TFormId
+ */
+union TFormId
+{
+ uint32 Id;
+
+ struct
+ {
+ uint32 Type : 8;
+ uint32 Id : 24;
+ } FormIDInfos;
+
+ void serial(NLMISC::IStream &f) { f.serial(Id); }
+};
+
+bool operator<(const TFormId& fid1, const TFormId& fid2) { return fid1.Id FormToId;
+map IdToForm;
+map FileTypeToId;
+map IdToFileType;
+map TypeToLastId;
+set ExtensionsAllowed;
+
+// stat
+
+uint32 NbTypesAdded = 0;
+uint32 NbFilesAdded = 0;
+uint32 NbFilesAlreadyAdded = 0;
+uint32 NbFilesUnknownType = 0;
+uint32 NbFilesDiscarded = 0;
+
+//manageFile
+//void manageFile( WIN32_FIND_DATA& findFileData, list& dirs, string& currentDir );
+
+// addId
+void addId( string fileName );
+
+// getFileType
+bool getFileType( string& fileName, string& fileType );
+
+//-----------------------------------------------
+// getFirstFreeFileTypeId
+//
+//-----------------------------------------------
+sint16 getFirstFreeFileTypeId()
+{
+ for( sint16 id=0; id<256; ++id )
+ {
+ if( IdToFileType.find((uint8)id) == IdToFileType.end() )
+ {
+ return id;
+ }
+ }
+
+ return -1;
+
+} // getFirstFreeFileTypeId //
+
+
+//-----------------------------------------------
+// readFormId
+//
+//-----------------------------------------------
+void readFormId( string& outputFileName )
+{
+ CIFile f;
+ if( f.open( outputFileName ) )
+ {
+ f.serialCont( IdToForm );
+ }
+
+ // insert an unknown entry
+ TFormId formId;
+ formId.Id = 0;
+ IdToForm.insert( make_pair( formId, string("unknown.unknown") ) );
+
+ // remove integer file extensions (created by CVS) and init FileTypeToId (associates the form type to the form type id)
+ map::iterator itIF;
+ for( itIF = IdToForm.begin(); itIF != IdToForm.end(); )
+ {
+ // get the file type from form name
+ TFormId fid = (*itIF).first;
+ string fileType;
+
+ if((*itIF).second.empty() || (*itIF).second=="." || (*itIF).second==".." || (*itIF).second[0]=='_' || (*itIF).second.find(".#")==0)
+ {
+ map::iterator itErase = itIF;
+ ++itIF;
+ IdToForm.erase(itErase);
+ }
+ else
+ {
+ if( getFileType( (*itIF).second, fileType ) )
+ {
+ // insert the association (file type/file type id)
+ map::iterator itFT = FileTypeToId.find(fileType);
+ if( itFT == FileTypeToId.end() )
+ {
+ FileTypeToId.insert( make_pair(fileType,fid.FormIDInfos.Type) );
+ }
+ }
+ else
+ {
+ nlwarning("Unknown file type for the file : %s",(*itIF).second.c_str());
+ }
+ ++itIF;
+ }
+ }
+
+
+ // init FormToId (associates the form name to its id )
+ for( itIF = IdToForm.begin(); itIF != IdToForm.end(); ++itIF )
+ {
+ FormToId.insert( make_pair((*itIF).second,(*itIF).first) );
+ }
+
+ // init IdToFileType (associates the form type id to the form type name)
+ map::iterator itIFT;
+ for( itIFT = FileTypeToId.begin(); itIFT != FileTypeToId.end(); ++itIFT )
+ {
+ IdToFileType.insert( make_pair((*itIFT).second,(*itIFT).first) );
+ }
+
+ // init TypeToLastId (associates the type id to the last index used for this type)
+ for( itIF = IdToForm.begin(); itIF != IdToForm.end(); ++itIF )
+ {
+ uint8 type = (*itIF).first.FormIDInfos.Type;
+ uint32 id = (*itIF).first.FormIDInfos.Id;
+ map::iterator itTLI = TypeToLastId.find( type );
+ if( itTLI != TypeToLastId.end() )
+ {
+ if( (*itTLI).second < id )
+ {
+ (*itTLI).second = id;
+ }
+ }
+ else
+ {
+ TypeToLastId.insert( make_pair(type,id) );
+ }
+ }
+
+} // readFormId //
+
+
+
+
+//-----------------------------------------------
+// makeId
+//
+//-----------------------------------------------
+void makeId( list& dirs )
+{
+ list::const_iterator itDir;
+ for( itDir = dirs.begin(); itDir != dirs.end(); ++itDir )
+ {
+ nlinfo ("Searching files in directory '%s'...", (*itDir).c_str());
+ vector files;
+ CPath::getPathContent(*itDir,true,false,true,files);
+
+ nlinfo ("Found %d files in directory '%s'", files.size(), (*itDir).c_str());
+ for(uint i = 0; i < files.size(); i++)
+ {
+ addId(CFile::getFilename(files[i]));
+ }
+ }
+
+} // makeId //
+
+
+
+
+//-----------------------------------------------
+// addId
+//
+//-----------------------------------------------
+void addId( string fileName )
+{
+ if(fileName.empty() || fileName=="." || fileName==".." || fileName[0]=='_' || fileName.find(".#")==0)
+ {
+ //nlinfo("Discarding file '%s'", fileName.c_str());
+ NbFilesDiscarded++;
+ return;
+ }
+ else
+ {
+ if( !ExtensionsAllowed.empty() )
+ {
+ string extStr = CFile::getExtension( fileName );
+ if( ExtensionsAllowed.find(extStr) == ExtensionsAllowed.end() )
+ {
+ NbFilesDiscarded++;
+ return;
+ }
+ }
+ }
+
+ // if the file is new
+ map::iterator itFI = FormToId.find( fileName );
+ if( itFI == FormToId.end() )
+ {
+ // double check : if file not found we check with lower case version of filename
+ map::iterator itFILwr = FormToId.find( toLower(fileName) );
+ if( itFILwr != FormToId.end() )
+ {
+ nlwarning("Trying to add %s but the file %s is already known ! becareful with lower case and upper case.", fileName.c_str(), toLower(fileName).c_str());
+ NbFilesDiscarded++;
+ return;
+ }
+
+ string fileType;
+ if( getFileType( fileName, fileType ) )
+ {
+ map::iterator itFTI = FileTypeToId.find( fileType );
+ TFormId fid;
+
+ // if the type of this file is a new type
+ if( itFTI == FileTypeToId.end() )
+ {
+ sint16 firstFreeFileTypeId = getFirstFreeFileTypeId();
+ if( firstFreeFileTypeId == -1 )
+ {
+ nlwarning("MORE THAN 256 FILE TYPES!!!!");
+ }
+ else
+ {
+ FileTypeToId.insert( make_pair(fileType,(uint8)firstFreeFileTypeId) );
+ IdToFileType.insert( make_pair((uint8)firstFreeFileTypeId,fileType) );
+ TypeToLastId.insert( make_pair((uint8)firstFreeFileTypeId,0) );
+
+ fid.FormIDInfos.Type = (uint8)firstFreeFileTypeId;
+ fid.FormIDInfos.Id = 0;
+
+ nlinfo("Adding file type '%s' with id %d", fileType.c_str(), firstFreeFileTypeId);
+ NbTypesAdded++;
+ }
+ }
+ // else the file type already exist
+ else
+ {
+ // id of the file type
+ uint8 fileTypeId = (*itFTI).second;
+
+ // last id used for this file type
+ map::iterator itTLI = TypeToLastId.find(fileTypeId);
+ nlassert(itTLI != TypeToLastId.end());
+ (*itTLI).second++;
+
+ // add the new association
+ fid.FormIDInfos.Type = fileTypeId;
+ fid.FormIDInfos.Id = (*itTLI).second;
+ }
+ FormToId.insert( make_pair(fileName,fid) );
+ IdToForm.insert( make_pair(fid,fileName) );
+ nlinfo("Adding file '%s' id %d with type '%s' id %d", fileName.c_str(), fid.FormIDInfos.Id, fileType.c_str(), fid.FormIDInfos.Type);
+ NbFilesAdded++;
+ }
+ else
+ {
+ //nlinfo("Unknown file type for the file : '%s' --> not added",fileName.c_str());
+ NbFilesUnknownType++;
+ }
+ }
+ else
+ {
+ //nlinfo("Skipping file '%s', already in the file", fileName.c_str());
+ NbFilesAlreadyAdded++;
+ }
+} // addId //
+
+
+
+//-----------------------------------------------
+// getFileType
+//
+//-----------------------------------------------
+bool getFileType( string& fileName, string& fileType )
+{
+ fileType = CFile::getExtension(CFile::getFilename(fileName));
+ return !fileType.empty();
+
+} // getFileType //
+
+
+
+//-----------------------------------------------
+// display
+//
+//-----------------------------------------------
+void display()
+{
+ nldebug ("Output :");
+ map::iterator it1;
+ for( it1 = IdToForm.begin(); it1 != IdToForm.end(); ++it1 )
+ {
+ nldebug("type: %d id: %d file: %s", (*it1).first.FormIDInfos.Type, (*it1).first.FormIDInfos.Id, (*it1).second.c_str());
+ }
+
+} // display //
+
+#endif // SHEETBUILDER_H
diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp
new file mode 100644
index 000000000..314efe2be
--- /dev/null
+++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp
@@ -0,0 +1,211 @@
+// NeL - MMORPG Framework
+// Copyright (C) 2010 Winch Gate Property Limited
+//
+// 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 .
+
+#include "sheetbuilderconfgdialog.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+SheetBuilderConfigDialog::SheetBuilderConfigDialog(QWidget *parent) :
+ QDialog(parent)
+{
+ /*
+ * Paths
+ */
+ QLabel *lblPaths = new QLabel(tr("Paths:"));
+ lstPaths = new QListWidget;
+ lstPaths->addItem("");
+
+ QPushButton *btnAddPath = new QPushButton(tr("Add"));
+ connect(btnAddPath, SIGNAL(clicked()), SLOT(addPath()));
+ QPushButton *btnDeletePath = new QPushButton(tr("Delete"));
+ connect(btnDeletePath, SIGNAL(clicked()), SLOT(deletePath()));
+
+ QVBoxLayout *ltButtonsPaths = new QVBoxLayout();
+ ltButtonsPaths->addWidget(btnAddPath);
+ ltButtonsPaths->addWidget(btnDeletePath);
+ ltButtonsPaths->addStretch(1);
+
+ QHBoxLayout *ltPaths = new QHBoxLayout;
+ ltPaths->addWidget(lstPaths);
+ ltPaths->addLayout(ltButtonsPaths);
+
+ /*
+ * Output file
+ */
+ QLabel *lblOutputFile = new QLabel(tr("Output file:"));
+ txtOutputFile = new QLineEdit();
+ QPushButton *btnBrowse = new QPushButton(tr("Browse..."));
+ connect(btnBrowse, SIGNAL(clicked()), SLOT(browseOutput()));
+
+ QHBoxLayout *ltOutput = new QHBoxLayout();
+ ltOutput->addWidget(txtOutputFile);
+ ltOutput->addWidget(btnBrowse);
+
+ /*
+ * Extensions
+ */
+ QLabel *lblExtensions = new QLabel(tr("Allowed extensions:"));
+ lstExtensionsAllowed = new QListWidget();
+
+ QPushButton *btnAddExtension = new QPushButton(tr("Add"));
+ connect(btnAddExtension, SIGNAL(clicked()), SLOT(addExtension()));
+ QPushButton *btnDeleteExtension = new QPushButton(tr("Delete"));
+ connect(btnDeleteExtension, SIGNAL(clicked()), SLOT(deleteExtension()));
+
+ QVBoxLayout *ltButtonsExtensions = new QVBoxLayout();
+ ltButtonsExtensions->addWidget(btnAddExtension);
+ ltButtonsExtensions->addWidget(btnDeleteExtension);
+ ltButtonsExtensions->addStretch(1);
+
+ QHBoxLayout *ltExtensions = new QHBoxLayout();
+ ltExtensions->addWidget(lstExtensionsAllowed);
+ ltExtensions->addLayout(ltButtonsExtensions);
+
+ /*
+ * Buttons
+ */
+ QPushButton *btnOk = new QPushButton(tr("OK"));
+ connect(btnOk, SIGNAL(clicked()), SLOT(accept()));
+ connect(btnOk, SIGNAL(clicked()), SLOT(writeSettings()));
+
+ QPushButton *btnCancel = new QPushButton(tr("Cancel"));
+ connect(btnCancel, SIGNAL(clicked()), SLOT(reject()));
+
+ QHBoxLayout *ltButtons = new QHBoxLayout;
+ ltButtons->addStretch(1);
+ ltButtons->addWidget(btnOk);
+ ltButtons->addWidget(btnCancel);
+
+ /*
+ * Main layout
+ */
+ QVBoxLayout *ltMain = new QVBoxLayout;
+ ltMain->addWidget(lblPaths);
+ ltMain->addLayout(ltPaths);
+ ltMain->addWidget(lblOutputFile);
+ ltMain->addLayout(ltOutput);
+ ltMain->addWidget(lblExtensions);
+ ltMain->addLayout(ltExtensions);
+ ltMain->addLayout(ltButtons);
+
+ setLayout(ltMain);
+ setWindowTitle(tr("Sheet builder configuration"));
+ resize(500, 450);
+ readSettings();
+}
+
+void SheetBuilderConfigDialog::addPath()
+{
+ QString path =
+ QFileDialog::getExistingDirectory(this, "Choose path");
+ if (!path.isEmpty()) {
+ QListWidgetItem *newItem = new QListWidgetItem;
+ newItem->setText(path);
+ newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+ lstPaths->addItem(newItem);
+ lstPaths->setCurrentItem(newItem);
+ }
+}
+
+void SheetBuilderConfigDialog::addExtension()
+{
+ QListWidgetItem *newItem = new QListWidgetItem;
+ newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+ lstExtensionsAllowed->addItem(newItem);
+ lstExtensionsAllowed->setCurrentItem(newItem);
+}
+
+void SheetBuilderConfigDialog::deletePath()
+{
+ QListWidgetItem *removeItem = lstPaths->takeItem(lstPaths->currentRow());
+ if (!removeItem)
+ delete removeItem;
+}
+
+void SheetBuilderConfigDialog::deleteExtension()
+{
+ QListWidgetItem *removeItem
+ = lstExtensionsAllowed->takeItem(lstExtensionsAllowed->currentRow());
+ if (!removeItem)
+ delete removeItem;
+}
+
+void SheetBuilderConfigDialog::browseOutput()
+{
+ QString fileName =
+ QFileDialog::getSaveFileName(this,tr("Choose output file"), "");
+ if (!fileName.isEmpty())
+ txtOutputFile->setText(fileName);
+}
+
+void SheetBuilderConfigDialog::readSettings()
+{
+ QStringList paths;
+ QString outputFile;
+ QStringList extensions;
+
+ QSettings settings("ovqt_sheet_builder.ini", QSettings::IniFormat);
+
+ paths = settings.value("SheetPaths").toStringList();
+ outputFile = settings.value("SheetOutputFile").toString();
+ extensions = settings.value("ExtensionsAllowed").toStringList();
+
+ lstPaths->clear();
+ lstExtensionsAllowed->clear();
+
+ QListWidgetItem *newItem;
+
+ Q_FOREACH (QString path, paths) {
+ newItem = new QListWidgetItem;
+ newItem->setText(path);
+ newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+ lstPaths->addItem(newItem);
+ }
+
+ txtOutputFile->setText(outputFile);
+
+ Q_FOREACH (QString extension, extensions) {
+ newItem = new QListWidgetItem;
+ newItem->setText(extension);
+ newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+ lstExtensionsAllowed->addItem(newItem);
+ }
+}
+
+void SheetBuilderConfigDialog::writeSettings()
+{
+ QStringList paths;
+ for (int i = 0; i < lstPaths->count(); i++)
+ paths.push_back(lstPaths->item(i)->text());
+
+ QString outputFile = txtOutputFile->text();
+
+ QStringList extensions;
+ for (int i = 0; i < lstExtensionsAllowed->count(); i++)
+ extensions.push_back(lstExtensionsAllowed->item(i)->text());
+
+ QSettings settings("./ovqt_sheet_builder.ini", QSettings::IniFormat);
+ settings.setValue("SheetPaths", paths);
+ settings.setValue("SheetOutputFile", outputFile);
+ settings.setValue("ExtensionsAllowed", extensions);
+}
diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h
new file mode 100644
index 000000000..1d1f225f9
--- /dev/null
+++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h
@@ -0,0 +1,46 @@
+// NeL - MMORPG Framework
+// Copyright (C) 2010 Winch Gate Property Limited
+//
+// 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 SHEETBUILDERCONFGDIALOG_H
+#define SHEETBUILDERCONFGDIALOG_H
+
+#include
+
+class QListWidget;
+class QLineEdit;
+
+class SheetBuilderConfigDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit SheetBuilderConfigDialog(QWidget *parent = 0);
+
+private Q_SLOTS:
+ void addPath();
+ void addExtension();
+ void deletePath();
+ void deleteExtension();
+ void browseOutput();
+ void readSettings();
+ void writeSettings();
+
+private:
+ QListWidget *lstPaths;
+ QListWidget *lstExtensionsAllowed;
+ QLineEdit *txtOutputFile;
+};
+
+#endif // SHEETBUILDERCONFGDIALOG_H
diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp
new file mode 100644
index 000000000..1f49ef89c
--- /dev/null
+++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp
@@ -0,0 +1,212 @@
+// NeL - MMORPG Framework
+// Copyright (C) 2010 Winch Gate Property Limited
+//
+// 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 .
+
+#include "sheetbuilderdialog.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "sheetbuilder.h"
+#include "sheetbuilderconfgdialog.h"
+
+SheetBuilderDialog::SheetBuilderDialog(QWidget *parent) :
+ QDialog(parent)
+{
+
+ QPushButton *btnOk = new QPushButton(tr("Make sheet"));
+ connect(btnOk, SIGNAL(clicked()), SLOT(buildSheet()));
+
+ QPushButton *btnCancel = new QPushButton(tr("Close"));
+ connect(btnCancel, SIGNAL(clicked()), SLOT(reject()));
+
+ chckClean = new QCheckBox(tr("Clean unwanted types from input"));
+
+ txtOutput = new QTextEdit;
+ txtOutput->setMinimumHeight(300);
+ txtOutput->setMinimumWidth(500);
+ txtOutput->setReadOnly(true);
+ txtOutput->setFontFamily("Monospace, Courier New, monospace");
+
+ QPushButton *btnDetails = new QPushButton(tr("Show/Hide details..."));
+ connect(btnDetails, SIGNAL(clicked()), SLOT(detailsShowHide()));
+
+ QPushButton *btnConfig = new QPushButton(tr("Settings"));
+ connect(btnConfig, SIGNAL(clicked()), SLOT(showConfig()));
+
+ QHBoxLayout *ltButtons = new QHBoxLayout;
+ ltButtons->addWidget(btnConfig);
+ ltButtons->addWidget(btnDetails);
+ ltButtons->addStretch(1);
+ ltButtons->addWidget(btnOk);
+ ltButtons->addWidget(btnCancel);
+
+ QVBoxLayout *ltMain = new QVBoxLayout;
+ ltMain->addWidget(chckClean);
+ ltMain->addWidget(txtOutput, 1);
+ ltMain->addLayout(ltButtons);
+ ltMain->addStretch();
+
+ txtOutput->hide();
+ detailsVisible = false;
+
+ setLayout(ltMain);
+ defHeight = height();
+ defWidth = 500;
+ resize(defWidth, defHeight);
+ setWindowTitle(tr("Sheet builder"));
+}
+
+void SheetBuilderDialog::showConfig()
+{
+ SheetBuilderConfigDialog dlg(this);
+ dlg.exec();
+}
+
+void SheetBuilderDialog::detailsShowHide()
+{
+ if (!detailsVisible) {
+ defHeight = height();
+ defWidth = width();
+ }
+
+ detailsVisible = !detailsVisible;
+ txtOutput->setVisible(detailsVisible);
+
+ if (!detailsVisible) {
+ adjustSize();
+ resize(defWidth, defHeight);
+ }
+}
+
+void SheetBuilderDialog::displayInfo(QString str)
+{
+ txtOutput->append(str);
+}
+
+void SheetBuilderDialog::buildSheet()
+{
+ QStringList paths;
+ QString outputFile;
+ QStringList extensions;
+
+ QSettings settings("ovqt_sheet_builder.ini", QSettings::IniFormat);
+ paths = settings.value("SheetPaths").toStringList();
+ outputFile = settings.value("SheetOutputFile").toString();
+ extensions = settings.value("ExtensionsAllowed").toStringList();
+
+ bool clean = chckClean->isChecked();
+ string configFileName("ovqt_sheet_builder.ini");
+ string outputFileName(outputFile.toStdString());
+
+ if (outputFileName.empty()) {
+ displayInfo("Error: Output file is not specified");
+ return;
+ }
+
+ list inputDirs;
+ Q_FOREACH (QString str, paths)
+ inputDirs.push_back(str.toStdString());
+
+ // load the config files
+ CConfigFile configFile;
+ if(!CFile::fileExists(configFileName))
+ {
+ displayInfo(QString("Config file '%1' not found, working whithout filter").arg(configFileName.c_str()) );
+ }
+ else
+ {
+ Q_FOREACH (QString str, extensions) {
+ ExtensionsAllowed.insert(str.toStdString());
+ }
+ }
+
+ // get the current associations (read the sheet_id and fill the working structures)
+ readFormId( outputFileName );
+
+ // output path
+ sint lastSeparator = CFile::getLastSeparator(outputFileName);
+ string outputPath;
+ if( lastSeparator != -1 )
+ {
+ outputPath = outputFileName.substr(0,lastSeparator+1);
+ }
+
+ // erase the unwanted extensions from map (modify the map, save it, and quit)
+ if( clean )
+ {
+ if( ExtensionsAllowed.empty() )
+ displayInfo("None extension list provided, the input will not be cleaned");
+ else
+ {
+ map::iterator itSheets;
+ for( itSheets = IdToForm.begin(); itSheets != IdToForm.end(); )
+ {
+ string extStr = CFile::getExtension( (*itSheets).second );
+ if( !extStr.empty() )
+ {
+ if( ExtensionsAllowed.find(extStr) == ExtensionsAllowed.end() )
+ {
+ map::iterator itDel = itSheets++;
+ IdToForm.erase( itDel );
+ }
+ else
+ ++itSheets;
+ }
+ }
+ COFile f( outputFileName );
+ f.serialCont( IdToForm );
+ }
+ displayInfo("The file has been cleaned");
+ return;
+ }
+
+ // make the ids
+ makeId( inputDirs );
+
+ // save the new map
+ COFile f( outputFileName );
+ f.serialCont( IdToForm );
+
+ string sheetListFileName = outputPath + "sheets.txt";
+ COFile output;
+ if( !output.open(sheetListFileName,false,true) )
+ {
+ displayInfo(QString("Can't open output file %1").arg(sheetListFileName.c_str()));
+ return;
+ }
+ map::iterator it1;
+ for( it1 = IdToForm.begin(); it1 != IdToForm.end(); ++it1 )
+ {
+ string outputLine = " id: " + toString((*it1).first.Id) + " file: " + (*it1).second +"\n";
+ output.serialBuffer((uint8*)(const_cast(outputLine.data())),(uint)outputLine.size());
+ }
+
+ displayInfo ("------------- results ----------------");
+ displayInfo (QString("%1 files added in '%2'").arg(NbFilesAdded).arg(outputFileName.c_str()));
+ displayInfo (QString("%1 files discarded because they are empty, begin with .# _ and so on").arg(NbFilesDiscarded));
+ displayInfo (QString("%1 files skipped because don't have extension").arg(NbFilesUnknownType));
+ displayInfo (QString("%1 types added in '%1'").arg(NbTypesAdded).arg(outputFileName.c_str()));
+
+ displayInfo (QString("%1 supported file types :").arg(FileTypeToId.size()));
+ for ( map::iterator it = FileTypeToId.begin(); it != FileTypeToId.end(); ++it )
+ {
+ displayInfo(QString("%1").arg((*it).first.c_str()));
+ }
+}
diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h
new file mode 100644
index 000000000..77cc1ac39
--- /dev/null
+++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h
@@ -0,0 +1,47 @@
+// NeL - MMORPG Framework
+// Copyright (C) 2010 Winch Gate Property Limited
+//
+// 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 SHEETBUILDERDIALOG_H
+#define SHEETBUILDERDIALOG_H
+
+#include
+
+class QCheckBox;
+class QTextEdit;
+
+class SheetBuilderDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit SheetBuilderDialog(QWidget *parent = 0);
+ ~SheetBuilderDialog() {}
+
+private Q_SLOTS:
+ void buildSheet();
+ void detailsShowHide();
+ void showConfig();
+
+private:
+ void displayInfo(QString str);
+
+ int defHeight;
+ int defWidth;
+ bool detailsVisible;
+ QCheckBox *chckClean;
+ QTextEdit *txtOutput;
+};
+
+#endif // SHEETBUILDERDIALOG_H