mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-12-25 02:10:53 +00:00
Changed: Implemented mission validation.
This commit is contained in:
parent
4247257e77
commit
3e6d643056
6 changed files with 312 additions and 8 deletions
|
@ -1,17 +1,24 @@
|
||||||
#include "mission_compiler_main_window.h"
|
#include "mission_compiler_main_window.h"
|
||||||
#include "ui_mission_compiler_main_window.h"
|
#include "ui_mission_compiler_main_window.h"
|
||||||
|
#include "validation_file.h"
|
||||||
|
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QSignalMapper>
|
#include <QSignalMapper>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QColorDialog>
|
#include <QColorDialog>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
#include "../core/icore.h"
|
#include "../core/icore.h"
|
||||||
#include "../core/imenu_manager.h"
|
#include "../core/imenu_manager.h"
|
||||||
#include "../core/core_constants.h"
|
#include "../core/core_constants.h"
|
||||||
|
|
||||||
|
#include <nel/misc/common.h>
|
||||||
|
|
||||||
#include <nel/misc/path.h>
|
#include <nel/misc/path.h>
|
||||||
|
#include <nel/ligo/primitive_utils.h>
|
||||||
|
#include <nel/ligo/primitive.h>
|
||||||
|
#include <nel/ligo/ligo_config.h>
|
||||||
|
|
||||||
MissionCompilerMainWindow::MissionCompilerMainWindow(QWidget *parent) :
|
MissionCompilerMainWindow::MissionCompilerMainWindow(QWidget *parent) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
|
@ -19,6 +26,9 @@ MissionCompilerMainWindow::MissionCompilerMainWindow(QWidget *parent) :
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
m_compileLog = "";
|
||||||
|
updateCompileLog();
|
||||||
|
|
||||||
// Load the settings.
|
// Load the settings.
|
||||||
loadConfig();
|
loadConfig();
|
||||||
|
|
||||||
|
@ -51,7 +61,11 @@ MissionCompilerMainWindow::MissionCompilerMainWindow(QWidget *parent) :
|
||||||
ui->selectedPrimitivesList->setModel(m_selectedPrimitivesModel);
|
ui->selectedPrimitivesList->setModel(m_selectedPrimitivesModel);
|
||||||
|
|
||||||
connect(ui->filterEdit, SIGNAL(textEdited(const QString&)), this, SLOT(handleFilterChanged(const QString&)));
|
connect(ui->filterEdit, SIGNAL(textEdited(const QString&)), this, SLOT(handleFilterChanged(const QString&)));
|
||||||
|
connect(ui->actionValidate, SIGNAL(triggered()), this, SLOT(handleValidation()));
|
||||||
|
|
||||||
|
NLLIGO::Register();
|
||||||
|
m_ligoConfig.readPrimitiveClass(NLMISC::CPath::lookup("world_editor_classes.xml").c_str(), false);
|
||||||
|
NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &m_ligoConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MissionCompilerMainWindow::handleFilterChanged(const QString &text)
|
void MissionCompilerMainWindow::handleFilterChanged(const QString &text)
|
||||||
|
@ -60,6 +74,106 @@ void MissionCompilerMainWindow::handleFilterChanged(const QString &text)
|
||||||
m_filteredProxyModel->setFilterRegExp(*m_regexpFilter);
|
m_filteredProxyModel->setFilterRegExp(*m_regexpFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MissionCompilerMainWindow::handleValidation()
|
||||||
|
{
|
||||||
|
// First switch toolbox pages to show the compilation output.
|
||||||
|
ui->toolBox->setCurrentIndex(2);
|
||||||
|
|
||||||
|
m_compileLog.append("Begin mission validation.\n");
|
||||||
|
updateCompileLog();
|
||||||
|
|
||||||
|
// Load existing validation
|
||||||
|
CValidationFile validation;
|
||||||
|
validation.loadMissionValidationFile("mission_validation.cfg");
|
||||||
|
|
||||||
|
// Go through each file.
|
||||||
|
QStringList list = m_selectedPrimitivesModel->stringList();
|
||||||
|
QStringListIterator itr(list);
|
||||||
|
while(itr.hasNext())
|
||||||
|
{
|
||||||
|
QString filename = itr.next();
|
||||||
|
//QString filePath = NLMISC::CPath::lookup(filename.toAscii().data(), false).c_str();
|
||||||
|
m_compileLog.append("Parsing '"+filename+"'...\n");
|
||||||
|
updateCompileLog();
|
||||||
|
|
||||||
|
TMissionContainer missions;
|
||||||
|
NLLIGO::CPrimitives primDoc;
|
||||||
|
NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = &primDoc;
|
||||||
|
NLLIGO::loadXmlPrimitiveFile(primDoc, NLMISC::CPath::lookup(filename.toAscii().data(), false), m_ligoConfig);
|
||||||
|
parsePrimForMissions(primDoc.RootNode, missions);
|
||||||
|
|
||||||
|
// Parse missions to check modification
|
||||||
|
std::map<std::string, CMission>::iterator itMission, itMissionEnd = missions.end();
|
||||||
|
for (itMission=missions.begin(); itMission!=itMissionEnd; ++itMission)
|
||||||
|
{
|
||||||
|
CValidationFile::TMissionStateContainer::iterator itMissionValidation = validation._MissionStates.find(itMission->first);
|
||||||
|
if (itMissionValidation!=validation._MissionStates.end())
|
||||||
|
{
|
||||||
|
// Mission already registered, check hash key
|
||||||
|
if (itMissionValidation->second.hashKey!=itMission->second.hashKey)
|
||||||
|
{
|
||||||
|
itMissionValidation->second.hashKey = itMission->second.hashKey;
|
||||||
|
itMissionValidation->second.state = validation.defaultState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// New mission
|
||||||
|
validation.insertMission(itMission->first, itMission->second.hashKey);
|
||||||
|
}
|
||||||
|
m_compileLog.append("Mission: '"+QString(itMission->first.c_str())+"->"+QString(itMission->second.hashKey.c_str())+"\n");
|
||||||
|
updateCompileLog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
validation.saveMissionValidationFile("mission_validation.cfg");
|
||||||
|
|
||||||
|
m_compileLog.append("Validation finished");
|
||||||
|
updateCompileLog();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MissionCompilerMainWindow::parsePrimForMissions(NLLIGO::IPrimitive const *prim, TMissionContainer &missions)
|
||||||
|
{
|
||||||
|
std::string value;
|
||||||
|
// if the node is a mission parse it
|
||||||
|
if (prim->getPropertyByName("class",value) && !stricmp(value.c_str(),"mission") )
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
prim->getPropertyByName("name",name);
|
||||||
|
|
||||||
|
m_compileLog.append(" ** Parsing mission '"+QString(name.c_str())+"'\n");
|
||||||
|
updateCompileLog();
|
||||||
|
|
||||||
|
// parse the mission and put it in our manager
|
||||||
|
CMission mission(value, "");
|
||||||
|
if (!mission.parsePrim(prim) )
|
||||||
|
{
|
||||||
|
m_compileLog.append(" ** Previous errors in mission '"+QString(name.c_str())+"'");
|
||||||
|
updateCompileLog();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
missions.insert(make_pair(name, mission));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//this is not a mission node, so lookup recursively in the children
|
||||||
|
bool ok = true;
|
||||||
|
for (uint i=0;i<prim->getNumChildren();++i)
|
||||||
|
{
|
||||||
|
const NLLIGO::IPrimitive *child;
|
||||||
|
if ( !prim->getChild(child,i) || !parsePrimForMissions(child, missions) )
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MissionCompilerMainWindow::updateCompileLog()
|
||||||
|
{
|
||||||
|
ui->compileOutputText->setPlainText(m_compileLog);
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
|
||||||
void MissionCompilerMainWindow::loadConfig() {
|
void MissionCompilerMainWindow::loadConfig() {
|
||||||
QSettings *settings = Core::ICore::instance()->settings();
|
QSettings *settings = Core::ICore::instance()->settings();
|
||||||
settings->beginGroup("MissionCompiler");
|
settings->beginGroup("MissionCompiler");
|
||||||
|
|
|
@ -10,10 +10,15 @@
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
|
|
||||||
|
#include <nel/ligo/ligo_config.h>
|
||||||
|
#include <nel/ligo/primitive.h>
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class MissionCompilerMainWindow;
|
class MissionCompilerMainWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CMission;
|
||||||
|
|
||||||
class MissionCompilerMainWindow : public QMainWindow
|
class MissionCompilerMainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -26,18 +31,27 @@ public:
|
||||||
void saveConfig();
|
void saveConfig();
|
||||||
QUndoStack *getUndoStack() { return m_undoStack; }
|
QUndoStack *getUndoStack() { return m_undoStack; }
|
||||||
|
|
||||||
|
typedef std::map<std::string, CMission> TMissionContainer;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void handleFilterChanged(const QString &text);
|
void handleFilterChanged(const QString &text);
|
||||||
|
void handleValidation();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MissionCompilerMainWindow *ui;
|
Ui::MissionCompilerMainWindow *ui;
|
||||||
|
|
||||||
|
void updateCompileLog();
|
||||||
|
bool parsePrimForMissions(NLLIGO::IPrimitive const *prim, TMissionContainer &missions);
|
||||||
|
|
||||||
QMenu *_toolModeMenu;
|
QMenu *_toolModeMenu;
|
||||||
QUndoStack *m_undoStack;
|
QUndoStack *m_undoStack;
|
||||||
QStringListModel *m_allPrimitivesModel;
|
QStringListModel *m_allPrimitivesModel;
|
||||||
QStringListModel *m_selectedPrimitivesModel;
|
QStringListModel *m_selectedPrimitivesModel;
|
||||||
QSortFilterProxyModel *m_filteredProxyModel;
|
QSortFilterProxyModel *m_filteredProxyModel;
|
||||||
QRegExp *m_regexpFilter;
|
QRegExp *m_regexpFilter;
|
||||||
|
QString m_compileLog;
|
||||||
|
|
||||||
|
NLLIGO::CLigoConfig m_ligoConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MISSION_COMPILER_MAIN_WINDOW_H
|
#endif // MISSION_COMPILER_MAIN_WINDOW_H
|
||||||
|
|
|
@ -62,10 +62,6 @@ void MissionCompilerPlugin::extensionsInitialized()
|
||||||
//settings->beginGroup(Core::Constants::DATA_PATH_SECTION);
|
//settings->beginGroup(Core::Constants::DATA_PATH_SECTION);
|
||||||
//QString ligoConfigFile = settings->value(Core::Constants::DATA_PATH_SECTION).toString();
|
//QString ligoConfigFile = settings->value(Core::Constants::DATA_PATH_SECTION).toString();
|
||||||
//settings->beginGroup(Core::Constants::DATA_PATH_SECTION);
|
//settings->beginGroup(Core::Constants::DATA_PATH_SECTION);
|
||||||
|
|
||||||
NLLIGO::Register();
|
|
||||||
LigoConfig.readPrimitiveClass(NLMISC::CPath::lookup("world_editor_classes.xml").c_str(), false);
|
|
||||||
NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MissionCompilerPlugin::setNelContext(NLMISC::INelContext *nelContext)
|
void MissionCompilerPlugin::setNelContext(NLMISC::INelContext *nelContext)
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
// NeL includes
|
// NeL includes
|
||||||
#include <nel/misc/app_context.h>
|
#include <nel/misc/app_context.h>
|
||||||
#include <nel/misc/singleton.h>
|
#include <nel/misc/singleton.h>
|
||||||
#include <nel/ligo/primitive.h>
|
|
||||||
#include <nel/ligo/ligo_config.h>
|
|
||||||
|
|
||||||
// Qt includes
|
// Qt includes
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
@ -53,8 +51,6 @@ public:
|
||||||
QObject *objectByName(const QString &name) const;
|
QObject *objectByName(const QString &name) const;
|
||||||
ExtensionSystem::IPluginSpec *pluginByName(const QString &name) const;
|
ExtensionSystem::IPluginSpec *pluginByName(const QString &name) const;
|
||||||
|
|
||||||
NLLIGO::CLigoConfig LigoConfig;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NLMISC::CLibraryContext *_LibContext;
|
NLMISC::CLibraryContext *_LibContext;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
#include "validation_file.h"
|
||||||
|
|
||||||
|
#include <nel/misc/config_file.h>
|
||||||
|
#include <nel/misc/path.h>
|
||||||
|
|
||||||
|
void CValidationFile::loadMissionValidationFile(std::string filename)
|
||||||
|
{
|
||||||
|
// load the configuration file
|
||||||
|
NLMISC::CConfigFile cf;
|
||||||
|
std::string pathName = NLMISC::CPath::lookup(filename, false);
|
||||||
|
|
||||||
|
if (pathName.empty())
|
||||||
|
{
|
||||||
|
nlwarning("Can't find index file '%s' in search path, no mission will be valid", filename.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cf.load(pathName);
|
||||||
|
|
||||||
|
// get the variable
|
||||||
|
NLMISC::CConfigFile::CVar* var = cf.getVarPtr("AuthorizedStates");
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
for (uint i=0; i<var->size(); ++i)
|
||||||
|
_AuthorizedStates.push_back(var->asString(i));
|
||||||
|
}
|
||||||
|
int missionStatesFields = 3;
|
||||||
|
var = cf.getVarPtr("MissionStatesFields");
|
||||||
|
if (var)
|
||||||
|
missionStatesFields = var->asInt();
|
||||||
|
else
|
||||||
|
nlwarning("Mission validation file does not contain MissionStatesFields variable. Parsing may fail and corrupt data.");
|
||||||
|
|
||||||
|
var = cf.getVarPtr("MissionStates");
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
for (uint i=0; i<var->size()/missionStatesFields; ++i)
|
||||||
|
{
|
||||||
|
std::string mission = var->asString(i*missionStatesFields);
|
||||||
|
std::string stateName = var->asString(i*missionStatesFields+1);
|
||||||
|
std::string hashKey = var->asString(i*missionStatesFields+2);
|
||||||
|
_MissionStates.insert(std::make_pair(mission, CMissionState(mission, stateName, hashKey)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CValidationFile::saveMissionValidationFile(std::string filename)
|
||||||
|
{
|
||||||
|
// load the configuration file
|
||||||
|
std::string pathName = NLMISC::CPath::lookup(filename, false);
|
||||||
|
|
||||||
|
if (pathName.empty())
|
||||||
|
{
|
||||||
|
nlwarning("Can't find index file '%s' in search path, no mission will be valid", filename.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FILE* file = fopen(pathName.c_str(), "w");
|
||||||
|
nlassert(file!=NULL);
|
||||||
|
|
||||||
|
// AuthorizedStates
|
||||||
|
fprintf(file, "%s",
|
||||||
|
"// AuthorizedStates contains the list of authorized states. EGS mission\n"
|
||||||
|
"// manager can accept any number of states. Default state is the first one.\n"
|
||||||
|
"AuthorizedStates = {\n");
|
||||||
|
std::deque<std::string>::iterator itAuth, itAuthEnd = _AuthorizedStates.end();
|
||||||
|
for (itAuth=_AuthorizedStates.begin(); itAuth!=itAuthEnd; ++itAuth)
|
||||||
|
fprintf(file, "\t\"%s\",\n", itAuth->c_str());
|
||||||
|
fprintf(file, "%s", "};\n\n");
|
||||||
|
|
||||||
|
// MissionStatesFields
|
||||||
|
fprintf(file, "%s",
|
||||||
|
"// MissionStatesFields contains the number of fields in MissionStates, for\n"
|
||||||
|
"// future compatibility purpose.\n"
|
||||||
|
"MissionStatesFields = ");
|
||||||
|
fprintf(file, "%d", 3); // 3 fields: name, state, hash key
|
||||||
|
fprintf(file, "%s", ";\n\n");
|
||||||
|
|
||||||
|
// MissionStates
|
||||||
|
fprintf(file, "%s",
|
||||||
|
"// MissionStates contains a list of mission with for each the state of the\n"
|
||||||
|
"// mission and its hash key. The tool will add new missions with the default\n"
|
||||||
|
"// state. It will flag missions with a modified hash key with default state to\n"
|
||||||
|
"// prevent untested modified missions to be published.\n"
|
||||||
|
"// :NOTE: You can add a field to this structure without the need to modify EGS\n"
|
||||||
|
"// code. Simply update MissionStatesFields.\n"
|
||||||
|
"MissionStates = {\n");
|
||||||
|
TMissionStateContainer::iterator itMission, itMissionEnd = _MissionStates.end();
|
||||||
|
for (itMission=_MissionStates.begin(); itMission!=itMissionEnd; ++itMission)
|
||||||
|
fprintf(file, "\t%-42s %-12s \"%s\",\n", ("\""+itMission->second.name+"\",").c_str(), ("\""+itMission->second.state+"\",").c_str(), itMission->second.hashKey.c_str());
|
||||||
|
fprintf(file, "};\n\n");
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// :NOTE: This function exists in mission_template.cpp. If you change it here modify the other file.
|
||||||
|
std::string buildHashKey(std::string const& content)
|
||||||
|
{
|
||||||
|
uint32 sum = 0;
|
||||||
|
size_t size = content.length()/4;
|
||||||
|
for (size_t i=0; i<size; ++i)
|
||||||
|
{
|
||||||
|
uint32 val = 0;
|
||||||
|
for (int j=0; j<4; ++j)
|
||||||
|
val += content[4*i+j]<<8*j;
|
||||||
|
sum += val;
|
||||||
|
if (sum&1)
|
||||||
|
sum = sum>>1 | 0x80000000;
|
||||||
|
else
|
||||||
|
sum = sum>>1;
|
||||||
|
}
|
||||||
|
return NLMISC::toString("0x%08X", sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMission::parsePrim(NLLIGO::IPrimitive const* prim)
|
||||||
|
{
|
||||||
|
// init default values
|
||||||
|
std::vector<std::string>* params;
|
||||||
|
// get the mission script
|
||||||
|
if (!prim->getPropertyByName("script", params) || !params)
|
||||||
|
{
|
||||||
|
nlwarning("ERROR : cant find mission script!!!!!!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse them
|
||||||
|
std::string content;
|
||||||
|
std::vector<std::string>::iterator itParam, itParamEnd = params->end();
|
||||||
|
for (itParam=params->begin(); itParam!=itParamEnd; ++itParam)
|
||||||
|
{
|
||||||
|
content += *itParam + "\n";
|
||||||
|
}
|
||||||
|
hashKey = buildHashKey(content);
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef VALIDATION_FILE_H
|
||||||
|
#define VALIDATION_FILE_H
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <nel/ligo/primitive.h>
|
||||||
|
|
||||||
|
struct CMissionState
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string state;
|
||||||
|
std::string hashKey;
|
||||||
|
CMissionState(std::string _name, std::string _state, std::string _hashKey)
|
||||||
|
: name(_name), state(_state), hashKey(_hashKey) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CMission
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string hashKey;
|
||||||
|
CMission(std::string _name, std::string _hashKey)
|
||||||
|
: name(_name), hashKey(_hashKey) { }
|
||||||
|
bool parsePrim(NLLIGO::IPrimitive const* prim);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CValidationFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::map<std::string, CMissionState> TMissionStateContainer;
|
||||||
|
std::deque<std::string> _AuthorizedStates;
|
||||||
|
TMissionStateContainer _MissionStates;
|
||||||
|
public:
|
||||||
|
// CValidationFile() { }
|
||||||
|
void loadMissionValidationFile(std::string filename);
|
||||||
|
void saveMissionValidationFile(std::string filename);
|
||||||
|
void insertMission(std::string const& mission, std::string const& hashKey)
|
||||||
|
{
|
||||||
|
_MissionStates.insert(std::make_pair(mission, CMissionState(mission, defaultState(), hashKey)));
|
||||||
|
}
|
||||||
|
std::string defaultState()
|
||||||
|
{
|
||||||
|
if (!_AuthorizedStates.empty())
|
||||||
|
return _AuthorizedStates.front();
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VALIDATION_FILE_H
|
Loading…
Reference in a new issue