diff --git a/code/nel/tools/3d/CMakeLists.txt b/code/nel/tools/3d/CMakeLists.txt index 034fc5f55..57d297fc8 100644 --- a/code/nel/tools/3d/CMakeLists.txt +++ b/code/nel/tools/3d/CMakeLists.txt @@ -1,10 +1,20 @@ IF(WITH_NEL_TOOLS) IF(WITH_3D) + IF(WITH_QT5) + SUBDIRS( + shared_widgets + panoply_preview) + ENDIF() IF(WITH_ASSIMP) SUBDIRS( mesh_utils mesh_export) + IF(WITH_QT5) + # NOTE: Also requires C++11, because. + SUBDIRS( + mesh_editor) + ENDIF() ENDIF() SUBDIRS( anim_builder @@ -67,11 +77,6 @@ IF(WITH_NEL_TOOLS AND WITH_3D) ADD_SUBDIRECTORY(object_viewer_widget) ENDIF() - IF(WITH_QT5) - ADD_SUBDIRECTORY(shared_widgets) - ADD_SUBDIRECTORY(panoply_preview) - ENDIF() - IF(WITH_NEL_TOOLS) FIND_PACKAGE(Squish) ENDIF() diff --git a/code/nel/tools/3d/mesh_editor/CMakeLists.txt b/code/nel/tools/3d/mesh_editor/CMakeLists.txt new file mode 100644 index 000000000..465df646f --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/CMakeLists.txt @@ -0,0 +1,39 @@ + +FILE(GLOB SRCS *.cpp) +FILE(GLOB HDRS *.h) +IF (WIN32) + FILE(GLOB RSRC *.rc) +ENDIF (WIN32) +FILE(GLOB RESOURCES *.qrc) + +SOURCE_GROUP("" FILES ${SRCS} ${HDRS} ${RSRC} ${RESOURCES}) + +SET(CMAKE_AUTOMOC ON) + +QT5_ADD_RESOURCES(RESOURCE_ADDED ${RESOURCES}) + +ADD_EXECUTABLE(nl_mesh_editor WIN32 ${SRC} + ${SRCS} + ${HDRS} + ${RSRC} + ${RESOURCE_ADDED} + ${PANOPLY_MAKER} + ) + +IF(QT_STATIC) + SET(PANOPLY_PREVIEW_QT_LIBRARIES ${QT_LIBRARIES}) +ELSE() + SET(PANOPLY_PREVIEW_QT_LIBRARIES Qt5::Widgets) +ENDIF() + +TARGET_LINK_LIBRARIES(nl_mesh_editor + nelmisc + nel3d + nelsound + shared_widgets + mesh_utils) + +NL_DEFAULT_PROPS(nl_mesh_editor "NeL, Tools, 3D: Mesh Editor") +NL_ADD_RUNTIME_FLAGS(nl_mesh_editor) + +INSTALL(TARGETS nl_mesh_editor RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT samples3d) diff --git a/code/nel/tools/3d/mesh_editor/configuration.cpp b/code/nel/tools/3d/mesh_editor/configuration.cpp new file mode 100644 index 000000000..524a41c7b --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/configuration.cpp @@ -0,0 +1,242 @@ +// 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 +#include "configuration.h" + +// STL includes + +// NeL includes +#include +#include +#include +#include +#include + +using namespace std; +using namespace NLMISC; + +CConfiguration::CConfiguration() +{ + +} + +CConfiguration::~CConfiguration() +{ + +} + +void CConfiguration::init() +{ + // verify data + nlassert(m_ConfigCallbacks.empty()); + + // load config + std::string appData = CPath::getApplicationDirectory("NeL"); + m_ConfigFile.load(appData + "mesh_editor.cfg"); + + // log config + CConfiguration::setAndCallback("NegFiltersDebug", CConfigCallback(this, &CConfiguration::cfcbLogFilter)); + CConfiguration::setAndCallback("NegFiltersInfo", CConfigCallback(this, &CConfiguration::cfcbLogFilter)); + CConfiguration::setAndCallback("NegFiltersWarning", CConfigCallback(this, &CConfiguration::cfcbLogFilter)); + CConfiguration::setAndCallback("NegFiltersAssert", CConfigCallback(this, &CConfiguration::cfcbLogFilter)); + CConfiguration::setAndCallback("NegFiltersError", CConfigCallback(this, &CConfiguration::cfcbLogFilter)); + + // set the search paths (kinda important) + /* + CConfigFile::CVar *var; + var = m_ConfigFile.getVarPtr("SearchPaths"); + uint varsize = var->size(); + for (uint i = 0; i < varsize; ++i) + CPath::addSearchPath(var->asString(i), true, false); + var = m_ConfigFile.getVarPtr("RemapExtensions"); + varsize = var->size(); + for (uint i = 0; i < varsize; i += 2) + CPath::remapExtension(var->asString(i), var->asString(i + 1), true); + */ +} + +void CConfiguration::release() +{ + // bye bye log config + CConfigFile::CVar emptyVar; + emptyVar.Name = "NegFiltersDebug"; + CConfiguration::dropCallback(emptyVar.Name); + cfcbLogFilter(emptyVar); + emptyVar.Name = "NegFiltersInfo"; + CConfiguration::dropCallback(emptyVar.Name); + cfcbLogFilter(emptyVar); + emptyVar.Name = "NegFiltersWarning"; + CConfiguration::dropCallback(emptyVar.Name); + cfcbLogFilter(emptyVar); + emptyVar.Name = "NegFiltersAssert"; + CConfiguration::dropCallback(emptyVar.Name); + cfcbLogFilter(emptyVar); + emptyVar.Name = "NegFiltersError"; + CConfiguration::dropCallback(emptyVar.Name); + cfcbLogFilter(emptyVar); + + // save and release the config file + if (m_ConfigFile.exists("SaveConfig") && m_ConfigFile.getVarPtr("SaveConfig")->asBool()) + { + m_ConfigFile.save(); + } + m_ConfigFile.clear(); + + // release the search paths etc + CPath::releaseInstance(); + + // verify data + nlassert(!m_ConfigCallbacks.size()); +} + +void CConfiguration::updateUtilities() +{ + //H_AUTO2 + + CConfigFile::checkConfigFiles(); +} + +void CConfiguration::setAndCallback(const std::string &varName, CConfigCallback configCallback) +{ + m_ConfigCallbacks[varName] = configCallback; + m_ConfigFile.setCallback(varName, cbConfigCallback); + configCallback(*m_ConfigFile.getVarPtr(varName)); +} + +void CConfiguration::setCallback(const std::string &varName, CConfigCallback configCallback) +{ + m_ConfigCallbacks[varName] = configCallback; + m_ConfigFile.setCallback(varName, cbConfigCallback); +} + +void CConfiguration::dropCallback(const std::string &varName) +{ + m_ConfigFile.setCallback(varName, NULL); + m_ConfigCallbacks.erase(varName); +} + +float CConfiguration::getValue(const string &varName, float defaultValue) +{ + if (m_ConfigFile.exists(varName)) return m_ConfigFile.getVar(varName).asFloat(); + CConfigFile::CVar varToCopy; + varToCopy.forceAsDouble((double)defaultValue); + m_ConfigFile.insertVar(varName, varToCopy); + return defaultValue; +} + +double CConfiguration::getValue(const string &varName, double defaultValue) +{ + if (m_ConfigFile.exists(varName)) return m_ConfigFile.getVar(varName).asDouble(); + CConfigFile::CVar varToCopy; + varToCopy.forceAsDouble(defaultValue); + m_ConfigFile.insertVar(varName, varToCopy); + return defaultValue; +} + +int CConfiguration::getValue(const string &varName, int defaultValue) +{ + if (m_ConfigFile.exists(varName)) return m_ConfigFile.getVar(varName).asInt(); + CConfigFile::CVar varToCopy; + varToCopy.forceAsInt(defaultValue); + m_ConfigFile.insertVar(varName, varToCopy); + return defaultValue; +} + +string CConfiguration::getValue(const string &varName, const string &defaultValue) +{ + if (m_ConfigFile.exists(varName)) return m_ConfigFile.getVar(varName).asString(); + CConfigFile::CVar varToCopy; + varToCopy.forceAsString(defaultValue); + m_ConfigFile.insertVar(varName, varToCopy); + return defaultValue; +} + +ucstring CConfiguration::getValue(const string &varName, const ucstring &defaultValue) +{ + if (m_ConfigFile.exists(varName)) return ucstring::makeFromUtf8(m_ConfigFile.getVar(varName).asString()); + CConfigFile::CVar varToCopy; + varToCopy.forceAsString(defaultValue.toUtf8()); + m_ConfigFile.insertVar(varName, varToCopy); + return defaultValue; +} + +bool CConfiguration::getValue(const string &varName, bool defaultValue) +{ + if (m_ConfigFile.exists(varName)) return m_ConfigFile.getVar(varName).asBool(); + CConfigFile::CVar varToCopy; + varToCopy.forceAsInt(defaultValue ? 1 : 0); + m_ConfigFile.insertVar(varName, varToCopy); + return defaultValue; +} + +CRGBA CConfiguration::getValue(const string &varName, const CRGBA &defaultValue) +{ + if (m_ConfigFile.exists(varName)) + { + return getValue(m_ConfigFile.getVar(varName), defaultValue); + } + else + { + // create a new value only if one doesn't exist + CConfigFile::CVar varToCopy; + varToCopy.forceAsInt(defaultValue.R); + varToCopy.setAsInt(defaultValue.G, 1); + varToCopy.setAsInt(defaultValue.B, 2); + varToCopy.setAsInt(defaultValue.A, 3); + m_ConfigFile.insertVar(varName, varToCopy); + } + return defaultValue; +} + +CRGBA CConfiguration::getValue(const CConfigFile::CVar &var, const CRGBA &defaultValue) +{ + if (var.size() >= 3) + { + if (var.size() > 4) nlwarning("RGBA value in config value '%s' is too long, ignoring unused values"); + return CRGBA((uint8)var.asInt(0), (uint8)var.asInt(1), (uint8)var.asInt(2), var.size() >= 4 ? (uint8)var.asInt(3) : 255); + } + nlwarning("Invalid RGBA value in config value '%s', reverting to default { %i, %i, %i, %i }", var.Name.c_str(), (sint)defaultValue.R, (sint)defaultValue.G, (sint)defaultValue.B, (sint)defaultValue.A); + return defaultValue; +} + +void CConfiguration::cbConfigCallback(NLMISC::CConfigFile::CVar &var) +{ + CConfiguration::getInstance()->m_ConfigCallbacks[var.Name](var); +} + +void CConfiguration::cfcbLogFilter(CConfigFile::CVar &var) +{ + // from nel/net/service.cpp + CLog *log = NULL; + if (var.Name == "NegFiltersDebug") log = DebugLog; + else if (var.Name == "NegFiltersInfo") log = InfoLog; + else if (var.Name == "NegFiltersWarning") log = WarningLog; + else if (var.Name == "NegFiltersAssert") log = AssertLog; + else if (var.Name == "NegFiltersError") log = ErrorLog; + else nlstop; + + // remove all old filters from config file + CConfigFile::CVar &oldvar = m_ConfigFile.getVar(var.Name); + for (uint j = 0; j < oldvar.size(); j++) + log->removeFilter(oldvar.asString(j).c_str()); + + // add all new filters from config file + for (uint i = 0; i < var.size(); i++) + log->addNegativeFilter(var.asString(i).c_str()); +} + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/configuration.h b/code/nel/tools/3d/mesh_editor/configuration.h new file mode 100644 index 000000000..86f8bc161 --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/configuration.h @@ -0,0 +1,81 @@ +// 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 NLQT_CONFIGURATION_H +#define NLQT_CONFIGURATION_H +#include + +// STL includes +#include + +// NeL includes +#include +#include +#include +#include +#include + +typedef NLMISC::CCallback CConfigCallback; + +/** + * CConfiguration + * \brief CConfiguration + * \date 2010-02-05 15:44GMT + * \author Jan Boon (Kaetemi) + */ +class CConfiguration : public NLMISC::CManualSingleton // singleton due to cconfigfile issues +{ +public: + CConfiguration(); + virtual ~CConfiguration(); + + void init(); + void release(); + + void updateUtilities(); + + void setAndCallback(const std::string &varName, CConfigCallback configCallback); + void setCallback(const std::string &varName, CConfigCallback configCallback); + void dropCallback(const std::string &varName); + + float getValue(const std::string &varName, float defaultValue); + double getValue(const std::string &varName, double defaultValue); + int getValue(const std::string &varName, int defaultValue); + std::string getValue(const std::string &varName, const std::string &defaultValue); + ucstring getValue(const std::string &varName, const ucstring &defaultValue); + bool getValue(const std::string &varName, bool defaultValue); + NLMISC::CRGBA getValue(const std::string &varName, const NLMISC::CRGBA &defaultValue); + NLMISC::CRGBA getValue(const NLMISC::CConfigFile::CVar &var, const NLMISC::CRGBA &defaultValue); + + inline NLMISC::CConfigFile &getConfigFile() { return m_ConfigFile; } + +private: + static void cbConfigCallback(NLMISC::CConfigFile::CVar &var); + void cfcbLogFilter(NLMISC::CConfigFile::CVar &var); + +private: + CConfiguration(const CConfiguration &); + CConfiguration &operator=(const CConfiguration &); + +private: + NLMISC::CConfigFile m_ConfigFile; + std::map m_ConfigCallbacks; + +}; /* class CConfiguration */ + +#endif /* #ifndef NLQT_CONFIGURATION_H */ + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/data.qrc b/code/nel/tools/3d/mesh_editor/data.qrc new file mode 100644 index 000000000..02dae011d --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/data.qrc @@ -0,0 +1,7 @@ + + + data/andbasr.ttf + data/mesh_editor.cfg + data/mesh_editor_default.cfg + + diff --git a/code/nel/tools/3d/mesh_editor/data/andbasr.ttf b/code/nel/tools/3d/mesh_editor/data/andbasr.ttf new file mode 100644 index 000000000..d785cc9df Binary files /dev/null and b/code/nel/tools/3d/mesh_editor/data/andbasr.ttf differ diff --git a/code/nel/tools/3d/mesh_editor/data/mesh_editor.cfg b/code/nel/tools/3d/mesh_editor/data/mesh_editor.cfg new file mode 100644 index 000000000..07a67a08a --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/data/mesh_editor.cfg @@ -0,0 +1,12 @@ +RootConfigFilename = "mesh_editor_default.cfg"; +GraphicsEnabled = 1; +SoundEnabled = 1; +GraphicsDriver = "OpenGL"; +SoundDriver = "OpenAL"; +SoundDevice = ""; +LanguageCode = "en"; +FontName = "andbasr.ttf"; +FontShadow = 1; +BackgroundColor = { + 151, 156, 182 +}; diff --git a/code/nel/tools/3d/mesh_editor/data/mesh_editor_default.cfg b/code/nel/tools/3d/mesh_editor/data/mesh_editor_default.cfg new file mode 100644 index 000000000..ef8a4432a --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/data/mesh_editor_default.cfg @@ -0,0 +1,84 @@ +////////////////////////////////////////////////////////////////////////////// +// Config file for NeL Mesh Editor /////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +// +// This file is used to setup the NeL Mesh Editor tool. +// + + +////////////////////////////////////////////////////////////////////////////// +// NeL Mesh Editor /////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +// Log filters +NegFiltersDebug += { ".zonel", "FRONT: " }; +NegFiltersInfo += { }; +NegFiltersWarning += { ".zonel", "FRONT: " }; +NegFiltersAssert += { }; +NegFiltersError += { }; + +// The language code of the client +LanguageCode = "en"; + +// If changes to the config should be saved on exit +SaveConfig = 1; + + +////////////////////////////////////////////////////////////////////////////// +// Graphics ////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +// Use OpenGL or Direct3D (Windows) +GraphicsEnabled = 1; +GraphicsDrivers = { "OpenGL", "Direct3D" }; +GraphicsDriver = "OpenGL"; + +// Font name used for all text in the client (it can be a .ttf, .fon, .pfb) +FontName = "andbasr.ttf"; +FontShadow = 1; + +// Background color +BackgroundColor = { 151, 156, 182 }; + +// Screenshot formats +ScreenshotJPG = 1; +ScreenshotPNG = 1; +ScreenshotTGA = 0; + + +////////////////////////////////////////////////////////////////////////////// +// Environment /////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +SunDirection = { -2.935, +0.107, -1.22 }; +SunAmbient = { 190, 170, 150 }; +SunDiffuse = { 255, 248, 255 }; +SunSpecular = { 255, 255, 255}; + +// 1 if you want to see the fog +// FogEnable = 1; +// FogStart = 100.0; // in meter +// FogEnd = 250.0; // in meter +// FogColor = { 129, 136, 205 }; // { 147, 125, 114 }; + + +////////////////////////////////////////////////////////////////////////////// +// Sound ///////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +// The sound driver, choose between "Auto", "FMod", "DSound" and "OpenAl" +SoundEnabled = 0; +SoundDrivers = { "Auto", "OpenAL", "XAudio2", "FMod", "DSound" }; +SoundDriver = "OpenAL"; +SoundDevice = ""; +SoundMaxTrack = 48; +SoundEnableOccludeObstruct = 1; +SoundEnableReverb = 1; +SoundManualRolloff = 1; +SoundUseADPCM = 0; +SoundForceSoftware = 0; +SoundAutoLoadSample = 1; + + +// end of file diff --git a/code/nel/tools/3d/mesh_editor/graphics_config.cpp b/code/nel/tools/3d/mesh_editor/graphics_config.cpp new file mode 100644 index 000000000..31b782264 --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/graphics_config.cpp @@ -0,0 +1,256 @@ +// 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 +#include "graphics_config.h" + +// STL includes + +// Qt includes +#include +#include +#include + +// NeL includes +// #include + +// Project includes +#include "main_window.h" +#include "configuration.h" +#include "undo_redo_binders.h" + +using namespace std; +using namespace NLMISC; + +CGraphicsConfig::CGraphicsConfig(QWidget *parent, CConfiguration *configuration, QUndoStack *undoStack) + : QWidget(parent), m_Configuration(configuration), m_UndoStack(undoStack), + m_DriverGroup(NULL), m_Enabled(NULL), m_DriverLabel(NULL), m_Driver(NULL), + m_FontNameLabel(NULL), m_FontName(NULL), m_Apply(NULL), + m_RenderGroup(NULL), m_BackgroundColor(NULL), m_FontShadow(NULL), + m_ScreenshotGroup(NULL) +{ + nlassert(m_Configuration); + nlassert(m_UndoStack); + + QVBoxLayout *vboxLayout = new QVBoxLayout(); + + // Driver + { + nlassert(!m_DriverGroup); + m_DriverGroup = new QGroupBox(); + QVBoxLayout *groupVboxLayout = new QVBoxLayout(); + + // Enabled + { + nlassert(!m_Enabled); + m_Enabled = new QCheckBox(); + groupVboxLayout->addWidget(m_Enabled); + } + + // Driver + { + QHBoxLayout *hboxLayout = new QHBoxLayout(); + nlassert(!m_DriverLabel); + m_DriverLabel = new QLabel(); + nlassert(!m_Driver); + m_Driver = new QComboBox(); + m_DriverLabel->setBuddy(m_Driver); + hboxLayout->addWidget(m_DriverLabel); + hboxLayout->addWidget(m_Driver); + hboxLayout->setStretch(1, 1); + groupVboxLayout->addLayout(hboxLayout); + } + + // Font Name + { + QHBoxLayout *hboxLayout = new QHBoxLayout(); + nlassert(!m_FontNameLabel); + m_FontNameLabel = new QLabel(); + nlassert(!m_FontName); + m_FontName = new QLineEdit(); + m_FontNameLabel->setBuddy(m_FontName); + hboxLayout->addWidget(m_FontNameLabel); + hboxLayout->addWidget(m_FontName); + hboxLayout->setStretch(1, 1); + groupVboxLayout->addLayout(hboxLayout); + } + + // Apply + { + nlassert(!m_Apply); + m_Apply = new QPushButton(); + m_Apply->setDefault(true); + groupVboxLayout->addWidget(m_Apply); + connect(m_Apply, SIGNAL(pressed()), this, SLOT(applyPressed())); + } + + m_DriverGroup->setLayout(groupVboxLayout); + vboxLayout->addWidget(m_DriverGroup); + } + + // Render + { + nlassert(!m_RenderGroup); + m_RenderGroup = new QGroupBox(); + QVBoxLayout *groupVboxLayout = new QVBoxLayout(); + + // Background Color + { + m_BackgroundColor = new QtColorPicker(); + m_BackgroundColor->setStandardColors(); + groupVboxLayout->addWidget(m_BackgroundColor); + connect(m_BackgroundColor, SIGNAL(colorChanged(const QColor &)), this, SLOT(uicbBackgroundColor(const QColor &))); + } + + // Font Shadow + { + nlassert(!m_FontShadow); + m_FontShadow = new QCheckBox(); + groupVboxLayout->addWidget(m_FontShadow); + connect(m_FontShadow, SIGNAL(toggled(bool)), this, SLOT(uicbFontShadow(bool))); + } + + m_RenderGroup->setLayout(groupVboxLayout); + vboxLayout->addWidget(m_RenderGroup); + } + + // Screenshots + { + nlassert(!m_ScreenshotGroup); + m_ScreenshotGroup = new QGroupBox(); + QVBoxLayout *groupVboxLayout = new QVBoxLayout(); + + m_ScreenshotGroup->setLayout(groupVboxLayout); + vboxLayout->addWidget(m_ScreenshotGroup); + } + + vboxLayout->addStretch(); + setLayout(vboxLayout); + + // setup config file callbacks and initialize values + m_Configuration->setAndCallback("GraphicsEnabled", CConfigCallback(this, &CGraphicsConfig::cfcbGraphicsEnabled)); + m_Configuration->setCallback("GraphicsDriver", CConfigCallback(this, &CGraphicsConfig::cfcbGraphicsDriver)); + m_Configuration->setAndCallback("GraphicsDrivers", CConfigCallback(this, &CGraphicsConfig::cfcbGraphicsDrivers)); + m_Configuration->setAndCallback("FontName", CConfigCallback(this, &CGraphicsConfig::cfcbFontName)); + m_Configuration->setAndCallback("BackgroundColor", CConfigCallback(this, &CGraphicsConfig::cfcbBackgroundColor)); + m_Configuration->setAndCallback("FontShadow", CConfigCallback(this, &CGraphicsConfig::cfcbFontShadow)); + + // setup translation callback and initialize translation + incbTranslate(); + + // setup undo/redo automation + CUndoRedoBinderButton *undoRedoEnabled = new CUndoRedoBinderButton(m_Enabled, undoStack); + CUndoRedoBinderComboBox *undoRedoDriver = new CUndoRedoBinderComboBox(m_Driver, undoStack); + CUndoRedoBinderLineEdit *undoRedoFontName = new CUndoRedoBinderLineEdit(m_FontName, undoStack); + CUndoRedoBinderColorPicker *undoRedoBackgroundColor = new CUndoRedoBinderColorPicker(m_BackgroundColor, undoStack); + CUndoRedoBinderButton *undoRedoFontShadow = new CUndoRedoBinderButton(m_FontShadow, undoStack); +} + +CGraphicsConfig::~CGraphicsConfig() +{ + m_Configuration->dropCallback("FontShadow"); + m_Configuration->dropCallback("BackgroundColor"); + m_Configuration->dropCallback("FontName"); + m_Configuration->dropCallback("GraphicsDrivers"); + m_Configuration->dropCallback("GraphicsDriver"); + m_Configuration->dropCallback("GraphicsEnabled"); +} + +void CGraphicsConfig::incbTranslate() +{ + m_DriverGroup->setTitle(tr("Driver Settings")); + m_Enabled->setText(tr("Enabled")); + m_DriverLabel->setText(tr("Driver: ")); + m_FontNameLabel->setText(tr("Font: ")); + m_Apply->setText(tr("Apply")); + + m_RenderGroup->setTitle(tr("Render Settings")); + m_BackgroundColor->setText(tr("Background Color")); + m_FontShadow->setText(tr("Font Shadow")); + + m_ScreenshotGroup->setTitle(tr("Screenshot Settings")); +} + +void CGraphicsConfig::cfcbGraphicsEnabled(NLMISC::CConfigFile::CVar &var) +{ + m_Enabled->setChecked(var.asBool()); +} + +void CGraphicsConfig::cfcbGraphicsDrivers(NLMISC::CConfigFile::CVar &var) +{ + while (m_Driver->count()) + m_Driver->removeItem(0); + for (uint i = 0; i < var.size(); ++i) + m_Driver->addItem(var.asString(i).c_str()); + cfcbGraphicsDriver(m_Configuration->getConfigFile().getVar("GraphicsDriver")); + m_UndoStack->clear(); +} + +void CGraphicsConfig::cfcbGraphicsDriver(NLMISC::CConfigFile::CVar &var) +{ + QString value = var.asString().c_str(); + QString dn = value.toLower(); + for (sint i = 0; i < m_Driver->count(); ++i) + { + if (dn == m_Driver->itemText(i).toLower()) + { + m_Driver->setCurrentIndex(i); + return; + } + } + nlwarning("Unknown GraphicsDriver specified in config, skipping value."); +} + +void CGraphicsConfig::cfcbFontName(NLMISC::CConfigFile::CVar &var) +{ + m_FontName->setText(var.asString().c_str()); +} + +void CGraphicsConfig::cfcbBackgroundColor(NLMISC::CConfigFile::CVar &var) +{ + m_BackgroundColor->setCurrentColor(QColor(var.asInt(0), var.asInt(1), var.asInt(2))); + emit onBackgroundColor(getBackgroundColor()); +} + +void CGraphicsConfig::cfcbFontShadow(NLMISC::CConfigFile::CVar &var) +{ + m_FontShadow->setChecked(var.asBool()); + emit onFontShadow(getFontShadow()); +} + +void CGraphicsConfig::applyPressed() +{ + m_Configuration->getConfigFile().getVar("GraphicsEnabled").setAsInt(getGraphicsEnabled() ? 1 : 0); + m_Configuration->getConfigFile().getVar("GraphicsDriver").setAsString(getGraphicsDriver()); + m_Configuration->getConfigFile().getVar("FontName").setAsString(getFontName()); + emit applyGraphicsConfig(); +} + +void CGraphicsConfig::uicbBackgroundColor(const QColor &backgroundColor) +{ + m_Configuration->getConfigFile().getVar("BackgroundColor").setAsInt(backgroundColor.red(), 0); + m_Configuration->getConfigFile().getVar("BackgroundColor").setAsInt(backgroundColor.green(), 1); + m_Configuration->getConfigFile().getVar("BackgroundColor").setAsInt(backgroundColor.blue(), 2); + emit onBackgroundColor(getBackgroundColor()); +} + +void CGraphicsConfig::uicbFontShadow(bool checked) +{ + m_Configuration->getConfigFile().getVar("FontShadow").setAsInt(checked ? 1 : 0); + emit onFontShadow(checked); +} + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/graphics_config.h b/code/nel/tools/3d/mesh_editor/graphics_config.h new file mode 100644 index 000000000..d6bd9757e --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/graphics_config.h @@ -0,0 +1,116 @@ +// 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 NLQT_GRAPHICS_CONFIG_H +#define NLQT_GRAPHICS_CONFIG_H +#include + +// STL includes + +// Qt includes +#include +#include +#include +#include +#include +#include +#include + +// NeL includes +#include +#include + +// Project includes +#include "qtcolorpicker.h" + +class QUndoStack; + +class CMainWindow; +class CConfiguration; + +/** + * CGraphicsConfig + * \brief CGraphicsConfig + * \date 2010-02-07 10:15GMT + * \author Jan Boon (Kaetemi) + */ +class CGraphicsConfig : public QWidget +{ + Q_OBJECT + +public: + CGraphicsConfig(QWidget *parent, CConfiguration *configuration, QUndoStack *undoStack); + virtual ~CGraphicsConfig(); + + void incbTranslate(); + + inline bool getGraphicsEnabled() const { return m_Enabled->isChecked(); } + inline std::string getGraphicsDriver() const { std::string v = std::string(m_Driver->currentText().toLatin1()); return v; } + inline std::string getFontName() const { std::string v = std::string(m_FontName->text().toLatin1()); return v; } + + inline NLMISC::CRGBA getBackgroundColor() const { QColor c = m_BackgroundColor->currentColor(); NLMISC::CRGBA v(c.red(), c.green(), c.blue()); return v; } + inline bool getFontShadow() const { return m_FontShadow->isChecked(); } + + inline bool getScreenshotJPG() const { return true; } + inline bool getScreenshotPNG() const { return true; } + inline bool getScreenshotTGA() const { return false; } + +private slots: + void applyPressed(); + void uicbBackgroundColor(const QColor &backgroundColor); + void uicbFontShadow(bool checked); + +signals: + /// GraphicsEnabled, GraphicsDriver, FontName + void applyGraphicsConfig(); + void onBackgroundColor(NLMISC::CRGBA backgroundColor); + void onFontShadow(bool fontShadow); + +private: + void cfcbGraphicsEnabled(NLMISC::CConfigFile::CVar &var); + void cfcbGraphicsDrivers(NLMISC::CConfigFile::CVar &var); + void cfcbGraphicsDriver(NLMISC::CConfigFile::CVar &var); + void cfcbFontName(NLMISC::CConfigFile::CVar &var); + void cfcbBackgroundColor(NLMISC::CConfigFile::CVar &var); + void cfcbFontShadow(NLMISC::CConfigFile::CVar &var); + +private: + CConfiguration *m_Configuration; + QUndoStack *m_UndoStack; + + QGroupBox *m_DriverGroup; + QCheckBox *m_Enabled; + QLabel *m_DriverLabel; + QComboBox *m_Driver; + QLabel *m_FontNameLabel; + QLineEdit *m_FontName; + QPushButton *m_Apply; + + QGroupBox *m_RenderGroup; + QtColorPicker *m_BackgroundColor; + QCheckBox *m_FontShadow; + + QGroupBox *m_ScreenshotGroup; + +private: + CGraphicsConfig(const CGraphicsConfig &); + CGraphicsConfig &operator=(const CGraphicsConfig &); + +}; /* class CGraphicsConfig */ + +#endif /* #ifndef NLQT_GRAPHICS_CONFIG_H */ + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/graphics_viewport.cpp b/code/nel/tools/3d/mesh_editor/graphics_viewport.cpp new file mode 100644 index 000000000..7a832ae75 --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/graphics_viewport.cpp @@ -0,0 +1,229 @@ +// 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 +#include "graphics_viewport.h" + +// STL includes + +// Qt includes +#include + +// NeL includes +#include +#include +#include +#include +#include +#include +#include +#include + +// Project includes +#include "graphics_config.h" + +using namespace std; +using namespace NLMISC; +using namespace NL3D; + +namespace { + +QString nli18n(const char *label) +{ + return QString::fromUtf16(CI18N::get(label).c_str()); +} + +} /* anonymous namespace */ + +CGraphicsViewport::CGraphicsViewport(QWidget *parent) + : QWidget(parent), + m_GraphicsConfig(NULL), + m_Driver(NULL), + m_TextContext(NULL) +{ + +} + +CGraphicsViewport::~CGraphicsViewport() +{ + +} + +void CGraphicsViewport::init(CGraphicsConfig *graphicsConfig) +{ + //H_AUTO2 + nldebug("CGraphicsViewport::init"); + + // copy parameters + m_GraphicsConfig = graphicsConfig; + + // check stuff we need + nlassert(m_GraphicsConfig); + + // create the driver + nlassert(!m_Driver); + m_Direct3D = false; + std::string driver = m_GraphicsConfig->getGraphicsDriver(); + if (driver == "Direct3D") m_Direct3D = true; //m_Driver = Direct3D; + else if (driver == "OpenGL") m_Direct3D = false; //m_Driver = OpenGL; + else + { + nlwarning("Invalid driver specified, defaulting to OpenGL"); + //m_Configuration->getConfigFile().getVar("GraphicsDriver").forceAsString("OpenGL"); + //m_Driver = OpenGL; + } + m_Driver = UDriver::createDriver(NULL, m_Direct3D, NULL); + nlassert(m_Driver); + + // initialize the window with config file values + m_Driver->setDisplay((nlWindow)winId(), NL3D::UDriver::CMode(width(), height(), 32)); + + // register config callbacks + connect(m_GraphicsConfig, SIGNAL(onBackgroundColor(NLMISC::CRGBA)), + this, SLOT(cfcbBackgroundColor(NLMISC::CRGBA))); + m_BackgroundColor = m_GraphicsConfig->getBackgroundColor(); + + // set the cache size for the font manager(in bytes) + m_Driver->setFontManagerMaxMemory(2097152); + + // create the text context + nlassert(!m_TextContext); + std::string localAppData = CPath::getApplicationDirectory("NeL", true); + std::string fontAppData = localAppData + m_GraphicsConfig->getFontName(); + m_TextContext = m_Driver->createTextContext(CFile::isExists(fontAppData) ? fontAppData : m_GraphicsConfig->getFontName()); + nlassert(m_TextContext); + connect(m_GraphicsConfig, SIGNAL(onFontShadow(bool)), + this, SLOT(cfcbFontShadow(bool))); + m_TextContext->setShaded(m_GraphicsConfig->getFontShadow()); +} + +void CGraphicsViewport::release() +{ + //H_AUTO2 + nldebug("CGraphicsViewport::release"); + + // release text context + nlassert(m_TextContext); + disconnect(m_GraphicsConfig, SIGNAL(onFontShadow(bool)), + this, SLOT(cfcbFontShadow(bool))); + m_Driver->deleteTextContext(m_TextContext); + m_TextContext = NULL; + + // release driver + nlassert(m_Driver); + disconnect(m_GraphicsConfig, SIGNAL(onBackgroundColor(NLMISC::CRGBA)), + this, SLOT(cfcbBackgroundColor(NLMISC::CRGBA))); + m_Driver->release(); + delete m_Driver; + m_Driver = NULL; + + // reset parameters + m_GraphicsConfig = NULL; +} + +void CGraphicsViewport::updateInput() +{ + m_Driver->EventServer.pump(); +} + +void CGraphicsViewport::renderDriver() +{ + m_Driver->clearBuffers(m_BackgroundColor); +} + +void CGraphicsViewport::renderDebug2D() +{ + m_TextContext->setColor(NL3D::CRGBA (255, 255, 255)); + m_TextContext->setFontSize(40); + m_TextContext->setHotSpot(NL3D::UTextContext::BottomLeft); + m_TextContext->printAt(0.3f, 0.5f, std::string("NeL Qt")); +} + +void CGraphicsViewport::cfcbBackgroundColor(NLMISC::CRGBA backgroundColor) +{ + m_BackgroundColor = backgroundColor; +} + +void CGraphicsViewport::cfcbFontShadow(bool fontShadow) +{ + m_TextContext->setShaded(fontShadow); +} + +QAction *CGraphicsViewport::createSaveScreenshotAction(QObject *parent) +{ + QAction *action = new QAction(parent); + connect(action, SIGNAL(triggered()), this, SLOT(saveScreenshot())); + return action; +} + +void CGraphicsViewport::saveScreenshot() +{ + saveScreenshot( + m_GraphicsConfig->getScreenshotJPG(), + m_GraphicsConfig->getScreenshotPNG(), + m_GraphicsConfig->getScreenshotTGA()); +} + +void CGraphicsViewport::saveScreenshot(bool jpg, bool png, bool tga) +{ + //H_AUTO2 + + // empty bitmap + CBitmap bitmap; + // copy the driver buffer to the bitmap + m_Driver->getBuffer(bitmap); + // create the file name + string filename = NLMISC::CPath::getApplicationDirectory("NeL") + "screenshots/mesh_editor_"; + // write the bitmap as a jpg, png or tga to the file + if (jpg) + { + string newfilename = CFile::findNewFile(filename + ".jpg"); + COFile outputFile(newfilename); + bitmap.writeJPG(outputFile, 100); + nlinfo("Screenshot '%s' saved", newfilename.c_str()); + } + if (png) + { + string newfilename = CFile::findNewFile(filename + ".png"); + COFile outputFile(newfilename); + bitmap.writePNG(outputFile, 24); + nlinfo("Screenshot '%s' saved", newfilename.c_str()); + } + if (tga) + { + string newfilename = CFile::findNewFile(filename + ".tga"); + COFile outputFile(newfilename); + bitmap.writeTGA(outputFile, 24, false); + nlinfo("Screenshot '%s' saved", newfilename.c_str()); + } +} + +void CGraphicsViewport::resizeEvent(QResizeEvent *resizeEvent) +{ + QWidget::resizeEvent(resizeEvent); + if (m_Driver && !m_Direct3D) + { + m_Driver->setMode(UDriver::CMode(resizeEvent->size().width(), resizeEvent->size().height(), 32)); + } + + // The OpenGL driver does not resize automatically. + // The Direct3D driver breaks the window mode to include window borders when calling setMode windowed. + + // Resizing the window after switching drivers a few times becomes slow. + // There is probably something inside the drivers not being released properly. +} + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/graphics_viewport.h b/code/nel/tools/3d/mesh_editor/graphics_viewport.h new file mode 100644 index 000000000..0419e8d7c --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/graphics_viewport.h @@ -0,0 +1,102 @@ +// 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 NLQT_GRAPHICS_VIEWPORT_H +#define NLQT_GRAPHICS_VIEWPORT_H +#include + +// STL includes + +// Qt includes +#include + +// NeL includes +#include +#include + +// Project includes + +class QAction; + +namespace NL3D { + class UDriver; + class UTextContext; + class UScene; +} + +class CGraphicsConfig; + +/** + * CGraphicsViewport + * \brief CGraphicsViewport + * \date 2010-02-06 10:11GMT + * \author Jan Boon (Kaetemi) + */ +class CGraphicsViewport : public QWidget +{ + Q_OBJECT + +public: + CGraphicsViewport(QWidget *parent); + virtual ~CGraphicsViewport(); + + virtual QPaintEngine* paintEngine() const { return NULL; } + + void init(CGraphicsConfig *graphicsConfig); + void release(); + + void updateInput(); + void renderDriver(); + void renderDebug2D(); + + QAction *createSaveScreenshotAction(QObject *parent); + + void saveScreenshot(bool jpg, bool png, bool tga); + + inline NL3D::UDriver *getDriver() { return m_Driver; } + inline NL3D::UTextContext *getTextContext() { return m_TextContext; } + inline NL3D::UScene *getScene() { return m_Scene; } + +public slots: + void saveScreenshot(); + +private slots: + void cfcbBackgroundColor(NLMISC::CRGBA backgroundColor); + void cfcbFontShadow(bool fontShadow); + +private: + virtual void resizeEvent(QResizeEvent *resizeEvent); + +private: + NLMISC::CRGBA m_BackgroundColor; + + CGraphicsConfig *m_GraphicsConfig; + + NL3D::UDriver *m_Driver; + NL3D::UTextContext *m_TextContext; + NL3D::UScene *m_Scene; + + bool m_Direct3D; + +private: + CGraphicsViewport(const CGraphicsViewport &); + CGraphicsViewport &operator=(const CGraphicsViewport &); + +}; /* class CGraphicsViewport */ + +#endif /* #ifndef NLQT_GRAPHICS_VIEWPORT_H */ + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/greenpill.ico b/code/nel/tools/3d/mesh_editor/greenpill.ico new file mode 100644 index 000000000..d2b9e8a20 Binary files /dev/null and b/code/nel/tools/3d/mesh_editor/greenpill.ico differ diff --git a/code/nel/tools/3d/mesh_editor/icon.rc b/code/nel/tools/3d/mesh_editor/icon.rc new file mode 100644 index 000000000..64e741cac --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/icon.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "greenpill.ico" \ No newline at end of file diff --git a/code/nel/tools/3d/mesh_editor/main.cpp b/code/nel/tools/3d/mesh_editor/main.cpp new file mode 100644 index 000000000..0d6b8aa5e --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/main.cpp @@ -0,0 +1,158 @@ +// NeL - MMORPG Framework +// Copyright (C) 2014 Jan BOON (jan.boon@kaetemi.be) +// +// 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 + +// STL includes +#include +#ifdef NL_OS_WINDOWS +# include +# include +# include +#endif + +// Qt includes +#include + +#ifdef Q_COMPILER_RVALUE_REFS +#undef Q_COMPILER_RVALUE_REFS +#endif + +#include +#include +#include +#include + +#ifdef QT_STATICPLUGIN + +#include + +#if defined(Q_OS_WIN32) + Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) +#elif defined(Q_OS_MAC) + Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin) +#elif defined(Q_OS_UNIX) + Q_IMPORT_PLUGIN(QXcbIntegrationPlugin) +#endif + +#endif + +// NeL includes +#include +#include +#include +#include +#include +#include + +// Project includes +#include "../shared_widgets/common.h" +#include "main_window.h" + +using namespace std; +using namespace NLMISC; + +#define NLTOOLS_LOG_FILE "mesh_editor.log" + +namespace { + +CFileDisplayer *s_FileDisplayer = NULL; + +} /* anonymous namespace */ + +#ifdef NL_OS_WINDOWS +# ifdef _UNICODE +# define tstring wstring +# else +# define tstring string +# endif +#endif + +sint main(int argc, char **argv) +{ + // low fragmentation heap (windows) +#ifdef NL_OS_WINDOWS + ULONG heapFragValue = 2; // enable low fragmentation heap + if (HeapSetInformation(GetProcessHeap(), + HeapCompatibilityInformation, + &heapFragValue, sizeof(heapFragValue))) + { + nlinfo("HeapSetInformation OK!\n"); + } + else + { + nlwarning("HeapSetInformation FAIL! (%d)\n", GetLastError()); + } +#endif + +#ifdef NL_OS_WINDOWS + HRESULT hr; + hr = hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + bool coInitOk = (hr == S_OK) || (hr == S_FALSE); +#endif + + std::string localAppData = CPath::getApplicationDirectory("NeL", true); + std::string appData = CPath::getApplicationDirectory("NeL"); + CFile::createDirectoryTree(localAppData); + CFile::createDirectoryTree(appData); + CFile::createDirectoryTree(appData + "screenshots/"); + + QFile(":/data/andbasr.ttf").copy(QString::fromStdString(localAppData + "andbasr.ttf")); + QFile(":/data/mesh_editor_default.cfg").copy(QString::fromStdString(appData + "mesh_editor_default.cfg")); + if (!QFileInfo(QString::fromStdString(appData + "mesh_editor.cfg")).exists()) + QFile(":/data/mesh_editor.cfg").copy(QString::fromStdString(appData + "mesh_editor.cfg")); + + NLQT::preApplication(); + QApplication app(argc, const_cast(argv)); + NLQT::postApplication(); + + // go nel! + { + // use log.log if NEL_LOG_IN_FILE and NLTOOLS_USE_LOG_LOG defined as 1 + createDebug(NULL, false, false); + + // create log + // filedisplayer only deletes the 001 etc + if (CFile::isExists(localAppData + NLTOOLS_LOG_FILE)) + CFile::deleteFile(localAppData + NLTOOLS_LOG_FILE); + // initialize the log file + s_FileDisplayer = new CFileDisplayer(); + s_FileDisplayer->setParam(localAppData + NLTOOLS_LOG_FILE, true); + DebugLog->addDisplayer(s_FileDisplayer); + InfoLog->addDisplayer(s_FileDisplayer); + WarningLog->addDisplayer(s_FileDisplayer); + AssertLog->addDisplayer(s_FileDisplayer); + ErrorLog->addDisplayer(s_FileDisplayer); + + nlinfo("Welcome to NeL!"); + } + + CSheetId::initWithoutSheet(); + + CMainWindow mainWin; + mainWin.resize(1280, 720); + mainWin.show(); + + int result = app.exec(); + +#ifdef NL_OS_WINDOWS + if (coInitOk) CoUninitialize(); +#endif + + return result; +} + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/main_window.cpp b/code/nel/tools/3d/mesh_editor/main_window.cpp new file mode 100644 index 000000000..f25a548ad --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/main_window.cpp @@ -0,0 +1,482 @@ +// 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 +#include "main_window.h" + +// STL includes + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// NeL includes +// #include +#include + +// Project includes +#include "../shared_widgets/command_log.h" +#include "graphics_viewport.h" +#include "graphics_config.h" + +using namespace std; +using namespace NLMISC; +using namespace NLQT; + +CMainWindow::CMainWindow(QWidget *parent, Qt::WindowFlags flags) + : QMainWindow(parent, flags), + m_UndoStack(NULL), + m_IsGraphicsInitialized(false), m_IsGraphicsEnabled(false), + m_IsSoundInitialized(false), m_IsSoundEnabled(false), + m_Timer(NULL), m_GraphicsViewport(NULL), + m_CommandLog(NULL), m_CommandLogDock(NULL), + m_GraphicsConfig(NULL), m_GraphicsConfigScroll(NULL), m_GraphicsConfigDock(NULL), + m_FileMenu(NULL), m_EditMenu(NULL), m_ViewportMenu(NULL), m_WidgetsMenu(NULL), m_HelpMenu(NULL), + m_FileToolBar(NULL), m_EditToolBar(NULL), + m_AboutAct(NULL), m_QuitAct(NULL), m_PrintDebugAct(NULL), + m_UndoAct(NULL), m_RedoAct(NULL), m_SaveScreenshotAct(NULL), + m_IsExiting(false) +{ + setObjectName("CMainWindow"); + + m_UndoStack = new QUndoStack(this); + + m_Configuration.init(); + + m_GraphicsViewport = new CGraphicsViewport(this); + setCentralWidget(m_GraphicsViewport); + + createActions(); + createMenus(); + createToolBars(); + createStatusBar(); + createDockWindows(); + + m_Configuration.setAndCallback("LanguageCode", CConfigCallback(this, &CMainWindow::cfcbLanguageCode)); + + recalculateMinimumWidth(); + + // As a special case, a QTimer with a timeout of 0 will time out as soon as all the events in the window system's event queue have been processed. This can be used to do heavy work while providing a snappy user interface. + m_Timer = new QTimer(this); + connect(m_Timer, SIGNAL(timeout()), this, SLOT(updateRender())); + // timer->start(); // <- timeout 0 + // it's heavy on cpu, though, when no 3d driver initialized :) + m_Timer->start(40); // 25fps + + m_IsGraphicsEnabled = m_GraphicsConfig->getGraphicsEnabled(); + connect(m_GraphicsConfig, SIGNAL(applyGraphicsConfig()), this, SLOT(applyGraphicsConfig())); + m_Configuration.setAndCallback("SoundEnabled", CConfigCallback(this, &CMainWindow::cfcbSoundEnabled)); + +} + +CMainWindow::~CMainWindow() +{ + m_Timer->stop(); + updateInitialization(false); + + delete m_GraphicsConfig; m_GraphicsConfig = NULL; + + m_Configuration.dropCallback("SoundEnabled"); + m_Configuration.dropCallback("LanguageCode"); + + m_Configuration.release(); +} + +void CMainWindow::setVisible(bool visible) +{ + // called by show() + // code assuming visible window needed to init the 3d driver + if (visible != isVisible()) + { + if (visible) + { + QMainWindow::setVisible(true); + updateInitialization(true); + } + else + { + updateInitialization(false); + QMainWindow::setVisible(false); + } + } +} + +void CMainWindow::updateInitialization(bool visible) +{ + bool done; + do + { + done = true; // set false whenever change + bool wantSound = m_IsSoundEnabled && visible; + bool wantGraphics = m_IsGraphicsEnabled && visible; + // bool wantLandscape = wantGraphics && m_IsGraphicsInitialized && isLandscapeEnabled; + + // .. stuff that depends on other stuff goes on top to prioritize deinitialization + + // Landscape + // ... + + // Graphics (Driver) + if (m_IsGraphicsInitialized) + { + if (!wantGraphics) + { + m_IsGraphicsInitialized = false; + if (m_IsSoundInitialized) + m_SoundUtilities.releaseGraphics(); + m_GraphicsViewport->release(); + done = false; + } + } + else + { + if (wantGraphics) + { + m_GraphicsViewport->init(m_GraphicsConfig); + if (m_IsSoundInitialized) + m_SoundUtilities.initGraphics(m_GraphicsViewport); + m_IsGraphicsInitialized = true; + done = false; + } + } + + // Sound (AudioMixer) + if (m_IsSoundInitialized) + { + if (!wantSound) + { + m_IsSoundInitialized = false; + if (m_IsGraphicsInitialized) + m_SoundUtilities.releaseGraphics(); + m_SoundUtilities.release(); + done = false; + } + } + else + { + if (wantSound) + { + + m_SoundUtilities.init(&m_Configuration); + if (m_IsGraphicsInitialized) + m_SoundUtilities.initGraphics(m_GraphicsViewport); + m_IsSoundInitialized = true; + done = false; + } + } + + } while (!done); +} + +void CMainWindow::createActions() +{ + m_QuitAct = new QAction(this); + m_QuitAct->setShortcuts(QKeySequence::Quit); + connect(m_QuitAct, SIGNAL(triggered()), this, SLOT(close())); + + m_AboutAct = new QAction(this); + connect(m_AboutAct, SIGNAL(triggered()), this, SLOT(about())); + + m_PrintDebugAct = new QAction(this); + connect(m_PrintDebugAct, SIGNAL(triggered()), this, SLOT(printDebug())); + + m_UndoAct = m_UndoStack->createUndoAction(this); + m_UndoAct->setShortcuts(QKeySequence::Undo); + m_RedoAct = m_UndoStack->createRedoAction(this); + m_RedoAct->setShortcuts(QKeySequence::Redo); + + m_SaveScreenshotAct = m_GraphicsViewport->createSaveScreenshotAction(this); +} + +void CMainWindow::translateActions() +{ + m_QuitAct->setText(tr("&Exit")); + m_QuitAct->setStatusTip(tr("Close the NeL Qt application.")); + m_AboutAct->setText(tr("&About")); + m_AboutAct->setStatusTip(tr("Show the about box.")); + m_PrintDebugAct->setText(tr("Print Debug")); + m_PrintDebugAct->setStatusTip(tr("Print something to debug.")); + m_UndoAct->setText(tr("&Undo")); + m_UndoAct->setStatusTip(tr("Undo the last action.")); + m_RedoAct->setText(tr("&Redo")); + m_RedoAct->setStatusTip(tr("Redo the last undone action.")); + m_SaveScreenshotAct->setText(tr("Save &Screenshot")); + m_SaveScreenshotAct->setStatusTip(tr("Make a screenshot of the current viewport and save it to the default screenshot directory.")); +} + +void CMainWindow::createMenus() +{ + m_FileMenu = menuBar()->addMenu(QString::null); + //m_FileMenu->addAction(saveAct); + //m_FileMenu->addSeparator(); + m_FileMenu->addAction(m_QuitAct); + + m_EditMenu = menuBar()->addMenu(QString::null); + m_EditMenu->addAction(m_UndoAct); + m_EditMenu->addAction(m_RedoAct); + + m_ViewportMenu = menuBar()->addMenu(QString::null); + m_ViewportMenu->addAction(m_SaveScreenshotAct); + + m_WidgetsMenu = menuBar()->addMenu(QString::null); + + menuBar()->addSeparator(); + + m_HelpMenu = menuBar()->addMenu(QString::null); + m_HelpMenu->addAction(m_AboutAct); +} + +void CMainWindow::translateMenus() +{ + m_FileMenu->setTitle(tr("&File")); + m_EditMenu->setTitle(tr("&Edit")); + m_ViewportMenu->setTitle(tr("&Viewport")); + m_WidgetsMenu->setTitle(tr("&Widgets")); + m_HelpMenu->setTitle(tr("&Help")); +} + +void CMainWindow::createToolBars() +{ + m_FileToolBar = addToolBar(QString::null); + m_FileToolBar->addAction(m_QuitAct); + m_FileToolBar->addAction(m_PrintDebugAct); + + m_EditToolBar = addToolBar(QString::null); + m_EditToolBar->addAction(m_AboutAct); +} + +void CMainWindow::translateToolBars() +{ + m_FileToolBar->setWindowTitle(tr("File")); + m_EditToolBar->setWindowTitle(tr("Edit")); +} + +void CMainWindow::createStatusBar() +{ + statusBar()->showMessage(tr("Ready")); +} + +void CMainWindow::createDockWindows() +{ + //QDockWidget *dock = new QDockWidget(tr("Test1"), this); + //dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + //customerList = new QListWidget(dock); + //dock->setWidget(customerList); + //addDockWidget(Qt::RightDockWidgetArea, dock); + //m_WidgetsMenu->addAction(dock->toggleViewAction()); + + //dock = new QDockWidget(tr("Test2"), this); + //paragraphsList = new QListWidget(dock); + //dock->setWidget(paragraphsList); + //addDockWidget(Qt::RightDockWidgetArea, dock); + //m_WidgetsMenu->addAction(dock->toggleViewAction()); + + //connect(customerList, SIGNAL(currentTextChanged(QString)), + // this, SLOT(insertCustomer(QString))); + //connect(paragraphsList, SIGNAL(currentTextChanged(QString)), + // this, SLOT(addParagraph(QString))); + + //dock = new QDockWidget( + + // CommandLog (Console) + { + m_CommandLogDock = new QDockWidget(this); + m_CommandLogDock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); + m_CommandLog = new CCommandLogDisplayer(m_CommandLogDock); + m_CommandLogDock->setWidget(m_CommandLog); + addDockWidget(Qt::BottomDockWidgetArea, m_CommandLogDock); + m_WidgetsMenu->addAction(m_CommandLogDock->toggleViewAction()); + } + + // GraphicsConfig (Graphics Configuration) + { + m_GraphicsConfigDock = new QDockWidget(this); + m_GraphicsConfigDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + m_GraphicsConfigScroll = new QScrollArea(); + m_GraphicsConfigScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_GraphicsConfigScroll->setWidgetResizable(true); + m_GraphicsConfig = new CGraphicsConfig(m_GraphicsConfigDock, &m_Configuration, m_UndoStack); + m_GraphicsConfigScroll->setWidget(m_GraphicsConfig); + m_GraphicsConfigDock->setWidget(m_GraphicsConfigScroll); + addDockWidget(Qt::RightDockWidgetArea, m_GraphicsConfigDock); + m_WidgetsMenu->addAction(m_GraphicsConfigDock->toggleViewAction()); + } + + // AssetTree (Assets) + { + m_AssetTreeDock = new QDockWidget(this); + m_AssetTreeDock->setAllowedAreas(Qt::AllDockWidgetAreas); + m_AssetTreeView = new QTreeView(m_AssetTreeDock); + m_AssetTreeModel = new QDirModel(); + m_AssetTreeView->setModel(m_AssetTreeModel); + m_AssetTreeView->setSortingEnabled(true); + m_AssetTreeDock->setWidget(m_AssetTreeView); + addDockWidget(Qt::LeftDockWidgetArea, m_AssetTreeDock); + m_WidgetsMenu->addAction(m_AssetTreeDock->toggleViewAction()); + } +} + +void CMainWindow::translateDockWindows() +{ + m_CommandLogDock->setWindowTitle(tr("Console")); + m_GraphicsConfigDock->setWindowTitle(tr("Graphics Configuration")); + m_AssetTreeDock->setWindowTitle(tr("Asset Tree")); +} + +void CMainWindow::recalculateMinimumWidth() +{ + if (m_GraphicsConfigScroll) + m_GraphicsConfigScroll->setMinimumWidth(m_GraphicsConfig->minimumSizeHint().width() + m_GraphicsConfigScroll->minimumSizeHint().width()); +} + +void CMainWindow::applyGraphicsConfig() +{ + // reinitializes the graphics system completely + // heavy lifting is done in updateInitialization + m_IsGraphicsEnabled = false; + updateInitialization(isVisible()); + m_IsGraphicsEnabled = m_GraphicsConfig->getGraphicsEnabled(); + updateInitialization(isVisible()); +} + +void CMainWindow::cfcbSoundEnabled(NLMISC::CConfigFile::CVar &var) +{ + // temp, todo as above + m_IsSoundEnabled = var.asBool(); // update loop inits +} + +void CMainWindow::cfcbLanguageCode(NLMISC::CConfigFile::CVar &var) +{ + setWindowTitle(tr("NeL Mesh Editor")); + translateActions(); + translateMenus(); + translateToolBars(); + translateDockWindows(); + recalculateMinimumWidth(); +} + +void CMainWindow::about() +{ + QMessageBox::about(this, tr("NeL Mesh Editor"), tr("NeL Mesh Editor")); +} + +void CMainWindow::updateRender() +{ + updateInitialization(isVisible()); + + if (isVisible()) + { + + // call all update functions + // 01. Update Utilities (configuration etc) + m_Configuration.updateUtilities(); + + // 02. Update Time (deltas) + // ... + + // 03. Update Receive (network, servertime, receive messages) + // ... + + // 04. Update Input (keyboard controls, etc) + if (m_IsGraphicsInitialized) + m_GraphicsViewport->updateInput(); + + // 05. Update Weather (sky, snow, wind, fog, sun) + // ... + + // 06. Update Entities (movement, do after possible tp from incoming messages etc) + // - Move other entities + // - Update self entity + // - Move bullets + // ... + + // 07. Update Landscape (async zone loading near entity) + // ... + + // 08. Update Collisions (entities) + // - Update entities + // - Update move container (swap with Update entities? todo: check code!) + // - Update bullets + // ... + + // 09. Update Animations (playlists) + // - Needs to be either before or after entities, not sure, + // there was a problem with wrong order a while ago!!! + // ... + + // 10. Update Camera (depends on entities) + // ... + + // 11. Update Interface (login, ui, etc) + // ... + + // 12. Update Sound (sound driver) + if (m_IsSoundInitialized) + m_SoundUtilities.updateSound(); + + // 13. Update Send (network, send new position etc) + // ... + + // 14. Update Debug (stuff for dev) + // ... + + if (m_IsGraphicsInitialized && !m_GraphicsViewport->getDriver()->isLost()) + { + // 01. Render Driver (background color) + m_GraphicsViewport->renderDriver(); // clear all buffers + + // 02. Render Sky (sky scene) + // ... + + // 04. Render Scene (entity scene) + // ... + + // 05. Render Effects (flare) + // ... + + // 06. Render Interface 3D (player names) + // ... + + // 07. Render Debug 3D + // ... + + // 08. Render Interface 2D (chatboxes etc, optionally does have 3d) + // ... + + // 09. Render Debug 2D (stuff for dev) + m_GraphicsViewport->renderDebug2D(); + + // swap 3d buffers + m_GraphicsViewport->getDriver()->swapBuffers(); + } + } +} + +void CMainWindow::printDebug() +{ + nldebug("This is a debug message."); +} + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/main_window.h b/code/nel/tools/3d/mesh_editor/main_window.h new file mode 100644 index 000000000..1553a218d --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/main_window.h @@ -0,0 +1,184 @@ +// 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 NLQT_MAIN_WINDOW_H +#define NLQT_MAIN_WINDOW_H +#include + +// STL includes + +// Qt includes +#include + +// NeL includes +#include +#include +#include +#include +#include + +// Project includes +#include "configuration.h" +#include "sound_utilities.h" + +class QTreeView; +class QDirModel; +class QUndoStack; +class QScrollArea; +class QTimer; + +namespace NLMISC { + class CConfigFile; +} + +namespace NL3D { + class UDriver; + class UScene; + class UTextContext; + class UVisualCollisionManager; +} + +namespace NLPACS { + class UMoveContainer; + class UGlobalRetriever; +} + +namespace NLSOUND { + class UAudioMixer; + class CSoundAnimManager; +} + +namespace NLQT { + class CCommandLogDisplayer; +} + +class CGraphicsViewport; +class CGraphicsConfig; + +/** + * CMainWindow + * \brief CMainWindow + * \date 2010-02-05 13:01GMT + * \author Jan Boon (Kaetemi) + */ +class CMainWindow : public QMainWindow +{ + Q_OBJECT + +public: + CMainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0); + virtual ~CMainWindow(); + + virtual void setVisible(bool visible); + +private slots: + void applyGraphicsConfig(); + // void applySoundConfig(); + + void about(); + void updateRender(); + void printDebug(); + +private: + void updateInitialization(bool visible); + + void createActions(); + void translateActions(); + void createMenus(); + void translateMenus(); + void createToolBars(); + void translateToolBars(); + void createStatusBar(); + void createDockWindows(); + void translateDockWindows(); + + void recalculateMinimumWidth(); + + void cfcbSoundEnabled(NLMISC::CConfigFile::CVar &var); + + void cfcbLanguageCode(NLMISC::CConfigFile::CVar &var); + +private: + CMainWindow(const CMainWindow &); + CMainWindow &operator=(const CMainWindow &); + +private: + CConfiguration m_Configuration; + CSoundUtilities m_SoundUtilities; + + QUndoStack *m_UndoStack; + + bool m_IsExiting; + bool m_IsGraphicsInitialized, m_IsGraphicsEnabled; + bool m_IsSoundInitialized, m_IsSoundEnabled; + + QTimer *m_Timer; + CGraphicsViewport *m_GraphicsViewport; + + NLQT::CCommandLogDisplayer *m_CommandLog; + QDockWidget *m_CommandLogDock; + + CGraphicsConfig *m_GraphicsConfig; + QScrollArea *m_GraphicsConfigScroll; + QDockWidget *m_GraphicsConfigDock; + + QTreeView *m_AssetTreeView; + QDirModel *m_AssetTreeModel; + QDockWidget *m_AssetTreeDock; + + QMenu *m_FileMenu; + QMenu *m_EditMenu; + QMenu *m_ViewportMenu; + QMenu *m_WidgetsMenu; + QMenu *m_HelpMenu; + + QToolBar *m_FileToolBar; + QToolBar *m_EditToolBar; + + QAction *m_AboutAct; + QAction *m_QuitAct; + QAction *m_PrintDebugAct; + QAction *m_UndoAct; + QAction *m_RedoAct; + QAction *m_SaveScreenshotAct; + + //NLMISC::CConfigFile *ConfigFile; // owned by CConfiguration + //CLoadingScreen LoadingScreen; // owned by CLoading (special case, always available) + //NL3D::UDriver *Driver; // owned by CGraphics + //NL3D::UTextContext *TextContext; // owned by CGraphics + //NLSOUND::UAudioMixer *AudioMixer; // owned by CSound + //NLSOUND::CSoundAnimManager *SoundAnimManager; // owned by CSound + //THCOMMON::CSheetLoader *SheetLoader; // owned by initSheets and releaseSheets + //NL3D::UScene *Scene; // owned by CEnvironment + //NLPACS::UMoveContainer *MoveContainer; // owned by CEnvironment + //NLPACS::UGlobalRetriever *GlobalRetriever; /// The global retriever used for pacs // owned by CEnvironment + //NL3D::UVisualCollisionManager *VisualCollisionManager; /// The collision manager for ground snapping // owned by CEnvironment + //THCLIENT::CKeyBinder *KeyBinder; // owned by CInterface + + //NLMISC::TLocalTime LocalTime; // use for delta only // owned by CGameTime + //NLMISC::TLocalTime LocalTimeDelta; // owned by CGameTime + //NL3D::TGlobalAnimationTime AnimationTime; // owned by CGameTime + //NL3D::TAnimationTime AnimationTimeDelta; // owned by CGameTime + //float FramesPerSecond; // owned by CGameTime + //float FramesPerSecondSmooth; // owned by CGameTime + + //NLMISC::CVector DetailTargetPosition; // player or camera position for lod improvements // owned by camera + +}; /* class CMainWindow */ + +#endif /* #ifndef NLQT_MAIN_WINDOW_H */ + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/qtcolorpicker.cpp b/code/nel/tools/3d/mesh_editor/qtcolorpicker.cpp new file mode 100644 index 000000000..9a4ffb720 --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/qtcolorpicker.cpp @@ -0,0 +1,952 @@ +/**************************************************************************** +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +#include "qtcolorpicker_p.h" + +/*! + Constructs a QtColorPicker widget. The popup will display a grid + with \a cols columns, or if \a cols is -1, the number of columns + will be calculated automatically. + + If \a enableColorDialog is true, the popup will also have a "More" + button (signified by an ellipsis "...") that presents a + QColorDialog when clicked. + + After constructing a QtColorPicker, call insertColor() to add + individual colors to the popup grid, or call setStandardColors() + to add all the standard colors in one go. + + The \a parent argument is passed to QFrame's constructor. + + \sa QFrame +*/ +QtColorPicker::QtColorPicker(QWidget *parent, + int cols, bool enableColorDialog) + : QPushButton(parent), popup(0), withColorDialog(enableColorDialog) +{ + setFocusPolicy(Qt::StrongFocus); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + setAutoDefault(false); + setAutoFillBackground(true); + setCheckable(true); + + // Set text + setText(tr("Black")); + firstInserted = false; + + // Create and set icon + col = Qt::black; + dirty = true; + + // Create color grid popup and connect to it. + popup = new ColorPickerPopup(cols, withColorDialog, this); + connect(popup, SIGNAL(selected(const QColor &)), + SLOT(setCurrentColor(const QColor &))); + connect(popup, SIGNAL(hid()), SLOT(popupClosed())); + + // Connect this push button's pressed() signal. + connect(this, SIGNAL(toggled(bool)), SLOT(buttonPressed(bool))); +} + +/*! + Destructs the QtColorPicker. +*/ +QtColorPicker::~QtColorPicker() +{ +} + +/*! \internal + + Pops up the color grid, and makes sure the status of + QtColorPicker's button is right. +*/ +void QtColorPicker::buttonPressed(bool toggled) +{ + if (!toggled) + return; + + const QRect desktop = QApplication::desktop()->geometry(); + // Make sure the popup is inside the desktop. + QPoint pos = mapToGlobal(rect().bottomLeft()); + if (pos.x() < desktop.left()) + pos.setX(desktop.left()); + if (pos.y() < desktop.top()) + pos.setY(desktop.top()); + + if ((pos.x() + popup->sizeHint().width()) > desktop.width()) + pos.setX(desktop.width() - popup->sizeHint().width()); + if ((pos.y() + popup->sizeHint().height()) > desktop.bottom()) + pos.setY(desktop.bottom() - popup->sizeHint().height()); + popup->move(pos); + + if (ColorPickerItem *item = popup->find(col)) + item->setSelected(true); + + // Remove focus from this widget, preventing the focus rect + // from showing when the popup is shown. Order an update to + // make sure the focus rect is cleared. + clearFocus(); + update(); + + // Allow keyboard navigation as soon as the popup shows. + popup->setFocus(); + + // Execute the popup. The popup will enter the event loop. + popup->show(); +} + +/*! + \internal +*/ +void QtColorPicker::paintEvent(QPaintEvent *e) +{ + if (dirty) { + int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize); + QPixmap pix(iconSize, iconSize); + pix.fill(palette().button().color()); + + QPainter p(&pix); + + int w = pix.width(); // width of cell in pixels + int h = pix.height(); // height of cell in pixels + p.setPen(QPen(Qt::gray)); + p.setBrush(col); + p.drawRect(2, 2, w - 5, h - 5); + setIcon(QIcon(pix)); + + dirty = false; + } + QPushButton::paintEvent(e); +} + +/*! \internal + + Makes sure the button isn't pressed when the popup hides. +*/ +void QtColorPicker::popupClosed() +{ + setChecked(false); + setFocus(); +} + +/*! + Returns the currently selected color. + + \sa text() +*/ +QColor QtColorPicker::currentColor() const +{ + return col; +} + +/*! + Returns the color at position \a index. +*/ +QColor QtColorPicker::color(int index) const +{ + return popup->color(index); +} + +/*! + Adds the 17 predefined colors from the Qt namespace. + + (The names given to the colors, "Black", "White", "Red", etc., are + all translatable.) + + \sa insertColor() +*/ +void QtColorPicker::setStandardColors() +{ + insertColor(Qt::black, tr("Black")); + insertColor(Qt::white, tr("White")); + insertColor(Qt::red, tr("Red")); + insertColor(Qt::darkRed, tr("Dark red")); + insertColor(Qt::green, tr("Green")); + insertColor(Qt::darkGreen, tr("Dark green")); + insertColor(Qt::blue, tr("Blue")); + insertColor(Qt::darkBlue, tr("Dark blue")); + insertColor(Qt::cyan, tr("Cyan")); + insertColor(Qt::darkCyan, tr("Dark cyan")); + insertColor(Qt::magenta, tr("Magenta")); + insertColor(Qt::darkMagenta, tr("Dark magenta")); + insertColor(Qt::yellow, tr("Yellow")); + insertColor(Qt::darkYellow, tr("Dark yellow")); + insertColor(Qt::gray, tr("Gray")); + insertColor(Qt::darkGray, tr("Dark gray")); + insertColor(Qt::lightGray, tr("Light gray")); +} + + +/*! + Makes \a color current. If \a color is not already in the color grid, it + is inserted with the text "Custom". + + This function emits the colorChanged() signal if the new color is + valid, and different from the old one. +*/ +void QtColorPicker::setCurrentColor(const QColor &color) +{ + if (col == color || !color.isValid()) + return; + + ColorPickerItem *item = popup->find(color); + if (!item) { + insertColor(color, tr("Custom")); + item = popup->find(color); + } + + col = color; + setText(item->text()); + + dirty = true; + + popup->hide(); + repaint(); + + item->setSelected(true); + emit colorChanged(color); +} + +/*! + Adds the color \a color with the name \a text to the color grid, + at position \a index. If index is -1, the color is assigned + automatically assigned a position, starting from left to right, + top to bottom. +*/ +void QtColorPicker::insertColor(const QColor &color, const QString &text, int index) +{ + popup->insertColor(color, text, index); + if (!firstInserted) { + col = color; + setText(text); + firstInserted = true; + } +} + +/*! \property QtColorPicker::colorDialog + \brief Whether the ellipsis "..." (more) button is available. + + If this property is set to TRUE, the color grid popup will include + a "More" button (signified by an ellipsis, "...") which pops up a + QColorDialog when clicked. The user will then be able to select + any custom color they like. +*/ +void QtColorPicker::setColorDialogEnabled(bool enabled) +{ + withColorDialog = enabled; +} +bool QtColorPicker::colorDialogEnabled() const +{ + return withColorDialog; +} + +/*! + Pops up a color grid with Qt default colors at \a point, using + global coordinates. If \a allowCustomColors is true, there will + also be a button on the popup that invokes QColorDialog. + + For example: + + \code + void Drawer::mouseReleaseEvent(QMouseEvent *e) + { + if (e->button() & RightButton) { + QColor color = QtColorPicker::getColor(mapToGlobal(e->pos())); + } + } + \endcode +*/ +QColor QtColorPicker::getColor(const QPoint &point, bool allowCustomColors) +{ + ColorPickerPopup popup(-1, allowCustomColors); + + popup.insertColor(Qt::black, tr("Black"), 0); + popup.insertColor(Qt::white, tr("White"), 1); + popup.insertColor(Qt::red, tr("Red"), 2); + popup.insertColor(Qt::darkRed, tr("Dark red"), 3); + popup.insertColor(Qt::green, tr("Green"), 4); + popup.insertColor(Qt::darkGreen, tr("Dark green"), 5); + popup.insertColor(Qt::blue, tr("Blue"), 6); + popup.insertColor(Qt::darkBlue, tr("Dark blue"), 7); + popup.insertColor(Qt::cyan, tr("Cyan"), 8); + popup.insertColor(Qt::darkCyan, tr("Dark cyan"), 9); + popup.insertColor(Qt::magenta, tr("Magenta"), 10); + popup.insertColor(Qt::darkMagenta, tr("Dark magenta"), 11); + popup.insertColor(Qt::yellow, tr("Yellow"), 12); + popup.insertColor(Qt::darkYellow, tr("Dark yellow"), 13); + popup.insertColor(Qt::gray, tr("Gray"), 14); + popup.insertColor(Qt::darkGray, tr("Dark gray"), 15); + popup.insertColor(Qt::lightGray, tr("Light gray"), 16); + + popup.move(point); + popup.exec(); + return popup.lastSelected(); +} + +/*! \internal + + Constructs the popup widget. +*/ +ColorPickerPopup::ColorPickerPopup(int width, bool withColorDialog, + QWidget *parent) + : QFrame(parent, Qt::Popup) +{ + setFrameStyle(QFrame::StyledPanel); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + + setFocusPolicy(Qt::StrongFocus); + setMouseTracking(true); + cols = width; + + if (withColorDialog) + { + moreButton = new ColorPickerButton(this); + moreButton->setFixedWidth(24); + moreButton->setFixedHeight(21); + moreButton->setFrameRect(QRect(2, 2, 20, 17)); + connect(moreButton, SIGNAL(clicked()), SLOT(getColorFromDialog())); + } + else + { + moreButton = 0; + } + + eventLoop = 0; + grid = 0; + regenerateGrid(); +} + + +/*! \internal + + Destructs the popup widget. +*/ +ColorPickerPopup::~ColorPickerPopup() +{ + if (eventLoop) + eventLoop->exit(); +} + +/*! \internal + + If there is an item whole color is equal to \a col, returns a + pointer to this item; otherwise returns 0. +*/ +ColorPickerItem *ColorPickerPopup::find(const QColor &col) const +{ + for (int i = 0; i < items.size(); ++i) { + if (items.at(i) && items.at(i)->color() == col) + return items.at(i); + } + + return 0; +} + +/*! \internal + + Adds \a item to the grid. The items are added from top-left to + bottom-right. +*/ +void ColorPickerPopup::insertColor(const QColor &col, const QString &text, int index) +{ + // Don't add colors that we have already. + ColorPickerItem *existingItem = find(col); + ColorPickerItem *lastSelectedItem = find(lastSelected()); + + if (existingItem) { + if (lastSelectedItem && existingItem != lastSelectedItem) + lastSelectedItem->setSelected(false); + existingItem->setFocus(); + existingItem->setSelected(true); + return; + } + + ColorPickerItem *item = new ColorPickerItem(col, text, this); + + if (lastSelectedItem) { + lastSelectedItem->setSelected(false); + } + else { + item->setSelected(true); + lastSel = col; + } + item->setFocus(); + + connect(item, SIGNAL(selected()), SLOT(updateSelected())); + + if (index == -1) + index = items.count(); + + items.insert((unsigned int)index, item); + regenerateGrid(); + + update(); +} + +/*! \internal + +*/ +QColor ColorPickerPopup::color(int index) const +{ + if (index < 0 || index > (int) items.count() - 1) + return QColor(); + + ColorPickerPopup *that = (ColorPickerPopup *)this; + return that->items.at(index)->color(); +} + +/*! \internal + +*/ +void ColorPickerPopup::exec() +{ + show(); + + QEventLoop e; + eventLoop = &e; + (void) e.exec(); + eventLoop = 0; +} + +/*! \internal + +*/ +void ColorPickerPopup::updateSelected() +{ + QLayoutItem *layoutItem; + int i = 0; + while ((layoutItem = grid->itemAt(i)) != 0) { + QWidget *w = layoutItem->widget(); + if (w && w->inherits("ColorPickerItem")) { + ColorPickerItem *litem = reinterpret_cast(layoutItem->widget()); + if (litem != sender()) + litem->setSelected(false); + } + ++i; + } + + if (sender() && sender()->inherits("ColorPickerItem")) { + ColorPickerItem *item = (ColorPickerItem *)sender(); + lastSel = item->color(); + emit selected(item->color()); + } + + hide(); +} + +/*! \internal + +*/ +void ColorPickerPopup::mouseReleaseEvent(QMouseEvent *e) +{ + if (!rect().contains(e->pos())) + hide(); +} + +/*! \internal + + Controls keyboard navigation and selection on the color grid. +*/ +void ColorPickerPopup::keyPressEvent(QKeyEvent *e) +{ + int curRow = 0; + int curCol = 0; + + bool foundFocus = false; + for (int j = 0; !foundFocus && j < grid->rowCount(); ++j) { + for (int i = 0; !foundFocus && i < grid->columnCount(); ++i) { + if (widgetAt[j][i] && widgetAt[j][i]->hasFocus()) { + curRow = j; + curCol = i; + foundFocus = true; + break; + } + } + } + + switch (e->key()) { + case Qt::Key_Left: + if (curCol > 0) --curCol; + else if (curRow > 0) { --curRow; curCol = grid->columnCount() - 1; } + break; + case Qt::Key_Right: + if (curCol < grid->columnCount() - 1 && widgetAt[curRow][curCol + 1]) ++curCol; + else if (curRow < grid->rowCount() - 1) { ++curRow; curCol = 0; } + break; + case Qt::Key_Up: + if (curRow > 0) --curRow; + else curCol = 0; + break; + case Qt::Key_Down: + if (curRow < grid->rowCount() - 1) { + QWidget *w = widgetAt[curRow + 1][curCol]; + if (w) { + ++curRow; + } else for (int i = 1; i < grid->columnCount(); ++i) { + if (!widgetAt[curRow + 1][i]) { + curCol = i - 1; + ++curRow; + break; + } + } + } + break; + case Qt::Key_Space: + case Qt::Key_Return: + case Qt::Key_Enter: { + QWidget *w = widgetAt[curRow][curCol]; + if (w && w->inherits("ColorPickerItem")) { + ColorPickerItem *wi = reinterpret_cast(w); + wi->setSelected(true); + + QLayoutItem *layoutItem; + int i = 0; + while ((layoutItem = grid->itemAt(i)) != 0) { + QWidget *w = layoutItem->widget(); + if (w && w->inherits("ColorPickerItem")) { + ColorPickerItem *litem + = reinterpret_cast(layoutItem->widget()); + if (litem != wi) + litem->setSelected(false); + } + ++i; + } + + lastSel = wi->color(); + emit selected(wi->color()); + hide(); + } else if (w && w->inherits("QPushButton")) { + ColorPickerItem *wi = reinterpret_cast(w); + wi->setSelected(true); + + QLayoutItem *layoutItem; + int i = 0; + while ((layoutItem = grid->itemAt(i)) != 0) { + QWidget *w = layoutItem->widget(); + if (w && w->inherits("ColorPickerItem")) { + ColorPickerItem *litem + = reinterpret_cast(layoutItem->widget()); + if (litem != wi) + litem->setSelected(false); + } + ++i; + } + + lastSel = wi->color(); + emit selected(wi->color()); + hide(); + } + } + break; + case Qt::Key_Escape: + hide(); + break; + default: + e->ignore(); + break; + } + + widgetAt[curRow][curCol]->setFocus(); +} + +/*! \internal + +*/ +void ColorPickerPopup::hideEvent(QHideEvent *e) +{ + if (eventLoop) { + eventLoop->exit(); + } + + setFocus(); + + emit hid(); + QFrame::hideEvent(e); +} + +/*! \internal + +*/ +QColor ColorPickerPopup::lastSelected() const +{ + return lastSel; +} + +/*! \internal + + Sets focus on the popup to enable keyboard navigation. Draws + focusRect and selection rect. +*/ +void ColorPickerPopup::showEvent(QShowEvent *) +{ + bool foundSelected = false; + for (int i = 0; i < grid->columnCount(); ++i) { + for (int j = 0; j < grid->rowCount(); ++j) { + QWidget *w = widgetAt[j][i]; + if (w && w->inherits("ColorPickerItem")) { + if (((ColorPickerItem *)w)->isSelected()) { + w->setFocus(); + foundSelected = true; + break; + } + } + } + } + + if (!foundSelected) { + if (items.count() == 0) + setFocus(); + else + widgetAt[0][0]->setFocus(); + } +} + +/*! + +*/ +void ColorPickerPopup::regenerateGrid() +{ + widgetAt.clear(); + + int columns = cols; + if (columns == -1) + columns = (int) ceil(sqrt((float) items.count())); + + // When the number of columns grows, the number of rows will + // fall. There's no way to shrink a grid, so we create a new + // one. + if (grid) delete grid; + grid = new QGridLayout(this); + grid->setMargin(1); + grid->setSpacing(0); + + int ccol = 0, crow = 0; + for (int i = 0; i < items.size(); ++i) { + if (items.at(i)) { + widgetAt[crow][ccol] = items.at(i); + grid->addWidget(items.at(i), crow, ccol++); + if (ccol == columns) { + ++crow; + ccol = 0; + } + } + } + + if (moreButton) { + grid->addWidget(moreButton, crow, ccol); + widgetAt[crow][ccol] = moreButton; + } + updateGeometry(); +} + +/*! \internal + + Copies the color dialog's currently selected item and emits + itemSelected(). +*/ +void ColorPickerPopup::getColorFromDialog() +{ + bool ok; + QRgb rgb = QColorDialog::getRgba(lastSel.rgba(), &ok, parentWidget()); + if (!ok) + return; + + QColor col = QColor::fromRgba(rgb); + insertColor(col, tr("Custom"), -1); + lastSel = col; + emit selected(col); +} + +/*! + Constructs a ColorPickerItem whose color is set to \a color, and + whose name is set to \a text. +*/ +ColorPickerItem::ColorPickerItem(const QColor &color, const QString &text, + QWidget *parent) + : QFrame(parent), c(color), t(text), sel(false) +{ + setToolTip(t); + setFixedWidth(24); + setFixedHeight(21); +} + +/*! + Destructs a ColorPickerItem. + */ +ColorPickerItem::~ColorPickerItem() +{ +} + +/*! + Returns the item's color. + + \sa text() +*/ +QColor ColorPickerItem::color() const +{ + return c; +} + +/*! + Returns the item's text. + + \sa color() +*/ +QString ColorPickerItem::text() const +{ + return t; +} + +/*! + +*/ +bool ColorPickerItem::isSelected() const +{ + return sel; +} + +/*! + +*/ +void ColorPickerItem::setSelected(bool selected) +{ + sel = selected; + update(); +} + +/*! + Sets the item's color to \a color, and its name to \a text. +*/ +void ColorPickerItem::setColor(const QColor &color, const QString &text) +{ + c = color; + t = text; + setToolTip(t); + update(); +} + +/*! + +*/ +void ColorPickerItem::mouseMoveEvent(QMouseEvent *) +{ + setFocus(); + update(); +} + +/*! + +*/ +void ColorPickerItem::mouseReleaseEvent(QMouseEvent *) +{ + sel = true; + emit selected(); +} + +/*! + +*/ +void ColorPickerItem::mousePressEvent(QMouseEvent *) +{ + setFocus(); + update(); +} + +/*! + +*/ +void ColorPickerItem::paintEvent(QPaintEvent *) +{ + QPainter p(this); + int w = width(); // width of cell in pixels + int h = height(); // height of cell in pixels + + p.setPen( QPen( Qt::gray, 0, Qt::SolidLine ) ); + + if (sel) + p.drawRect(1, 1, w - 3, h - 3); + + p.setPen( QPen( Qt::black, 0, Qt::SolidLine ) ); + p.drawRect(3, 3, w - 7, h - 7); + p.fillRect(QRect(4, 4, w - 8, h - 8), QBrush(c)); + + if (hasFocus()) + p.drawRect(0, 0, w - 1, h - 1); +} + +/*! + +*/ +ColorPickerButton::ColorPickerButton(QWidget *parent) + : QFrame(parent) +{ + setFrameStyle(StyledPanel); +} + +/*! + +*/ +void ColorPickerButton::mousePressEvent(QMouseEvent *) +{ + setFrameShadow(Sunken); + update(); +} + +/*! + +*/ +void ColorPickerButton::mouseMoveEvent(QMouseEvent *) +{ + setFocus(); + update(); +} + +/*! + +*/ +void ColorPickerButton::mouseReleaseEvent(QMouseEvent *) +{ + setFrameShadow(Raised); + repaint(); + emit clicked(); +} + +/*! + +*/ +void ColorPickerButton::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Up + || e->key() == Qt::Key_Down + || e->key() == Qt::Key_Left + || e->key() == Qt::Key_Right) + { + qApp->sendEvent(parent(), e); + } + else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Space || e->key() == Qt::Key_Return) + { + setFrameShadow(Sunken); + update(); + } + else + { + QFrame::keyPressEvent(e); + } +} + +/*! + +*/ +void ColorPickerButton::keyReleaseEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Up + || e->key() == Qt::Key_Down + || e->key() == Qt::Key_Left + || e->key() == Qt::Key_Right) + { + qApp->sendEvent(parent(), e); + } + else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Space || e->key() == Qt::Key_Return) + { + setFrameShadow(Raised); + repaint(); + emit clicked(); + } + else + { + QFrame::keyReleaseEvent(e); + } + +} + +/*! + +*/ +void ColorPickerButton::focusInEvent(QFocusEvent *e) +{ + setFrameShadow(Raised); + update(); + QFrame::focusOutEvent(e); +} + +/*! + +*/ +void ColorPickerButton::focusOutEvent(QFocusEvent *e) +{ + setFrameShadow(Raised); + update(); + QFrame::focusOutEvent(e); +} + +/*! + +*/ +void ColorPickerButton::paintEvent(QPaintEvent *e) +{ + QFrame::paintEvent(e); + + QPainter p(this); + p.fillRect(contentsRect(), palette().button()); + + QRect r = rect(); + + int offset = frameShadow() == Sunken ? 1 : 0; + + QPen pen(palette().buttonText(), 1); + p.setPen(pen); + + p.drawRect(r.center().x() + offset - 4, r.center().y() + offset, 1, 1); + p.drawRect(r.center().x() + offset , r.center().y() + offset, 1, 1); + p.drawRect(r.center().x() + offset + 4, r.center().y() + offset, 1, 1); + if (hasFocus()) { + p.setPen( QPen( Qt::black, 0, Qt::SolidLine ) ); + p.drawRect(0, 0, width() - 1, height() - 1); + } + + p.end(); + +} diff --git a/code/nel/tools/3d/mesh_editor/qtcolorpicker.h b/code/nel/tools/3d/mesh_editor/qtcolorpicker.h new file mode 100644 index 000000000..a589f09d2 --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/qtcolorpicker.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +#ifndef QTCOLORPICKER_H +#define QTCOLORPICKER_H +#include +#include +#include + +#include +#include +#include + +#define QT_QTCOLORPICKER_EXPORT + +class ColorPickerPopup; + +class QT_QTCOLORPICKER_EXPORT QtColorPicker : public QPushButton +{ + Q_OBJECT + + Q_PROPERTY(bool colorDialog READ colorDialogEnabled WRITE setColorDialogEnabled) + +public: + QtColorPicker(QWidget *parent = 0, + int columns = -1, bool enableColorDialog = true); + + ~QtColorPicker(); + + void insertColor(const QColor &color, const QString &text = QString::null, int index = -1); + + QColor currentColor() const; + + QColor color(int index) const; + + void setColorDialogEnabled(bool enabled); + bool colorDialogEnabled() const; + + void setStandardColors(); + + static QColor getColor(const QPoint &pos, bool allowCustomColors = true); + +public Q_SLOTS: + void setCurrentColor(const QColor &col); + +Q_SIGNALS: + void colorChanged(const QColor &); + +protected: + void paintEvent(QPaintEvent *e); + +private Q_SLOTS: + void buttonPressed(bool toggled); + void popupClosed(); + +private: + ColorPickerPopup *popup; + QColor col; + bool withColorDialog; + bool dirty; + bool firstInserted; +}; + +#endif diff --git a/code/nel/tools/3d/mesh_editor/qtcolorpicker_p.h b/code/nel/tools/3d/mesh_editor/qtcolorpicker_p.h new file mode 100644 index 000000000..de4e9ae51 --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/qtcolorpicker_p.h @@ -0,0 +1,251 @@ +/**************************************************************************** +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qtcolorpicker.h" + +/*! \class QtColorPicker + + \brief The QtColorPicker class provides a widget for selecting + colors from a popup color grid. + + Users can invoke the color picker by clicking on it, or by + navigating to it and pressing Space. They can use the mouse or + arrow keys to navigate between colors on the grid, and select a + color by clicking or by pressing Enter or Space. The + colorChanged() signal is emitted whenever the color picker's color + changes. + + The widget also supports negative selection: Users can click and + hold the mouse button on the QtColorPicker widget, then move the + mouse over the color grid and release the mouse button over the + color they wish to select. + + The color grid shows a customized selection of colors. An optional + ellipsis "..." button (signifying "more") can be added at the + bottom of the grid; if the user presses this, a QColorDialog pops + up and lets them choose any color they like. This button is made + available by using setColorDialogEnabled(). + + When a color is selected, the QtColorPicker widget shows the color + and its name. If the name cannot be determined, the translatable + name "Custom" is used. + + The QtColorPicker object is optionally initialized with the number + of columns in the color grid. Colors are then added left to right, + top to bottom using insertColor(). If the number of columns is not + set, QtColorPicker calculates the number of columns and rows that + will make the grid as square as possible. + + \code + DrawWidget::DrawWidget(QWidget *parent, const char *name) + { + QtColorPicker *picker = new QtColorPicker(this); + picker->insertColor(red, "Red")); + picker->insertColor(QColor("green"), "Green")); + picker->insertColor(QColor(0, 0, 255), "Blue")); + picker->insertColor(white); + + connect(colors, SIGNAL(colorChanged(const QColor &)), SLOT(setCurrentColor(const QColor &))); + } + \endcode + + An alternative to adding colors manually is to initialize the grid + with QColorDialog's standard colors using setStandardColors(). + + QtColorPicker also provides a the static function getColor(), + which pops up the grid of standard colors at any given point. + + \img colorpicker1.png + \img colorpicker2.png + + \sa QColorDialog +*/ + +/*! \fn QtColorPicker::colorChanged(const QColor &color) + + This signal is emitted when the QtColorPicker's color is changed. + \a color is the new color. + + To obtain the color's name, use text(). +*/ + +/* + A class that acts very much like a QPushButton. It's not styled, + so we can expect the exact same look, feel and geometry + everywhere. Also, this button always emits clicked on + mouseRelease, even if the mouse button was not pressed inside the + widget. +*/ +class ColorPickerButton : public QFrame +{ + Q_OBJECT + +public: + ColorPickerButton(QWidget *parent); + +signals: + void clicked(); + +protected: + void mousePressEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void keyPressEvent(QKeyEvent *e); + void keyReleaseEvent(QKeyEvent *e); + void paintEvent(QPaintEvent *e); + void focusInEvent(QFocusEvent *e); + void focusOutEvent(QFocusEvent *e); +}; + +/* + This class represents each "color" or item in the color grid. +*/ +class ColorPickerItem : public QFrame +{ + Q_OBJECT + +public: + ColorPickerItem(const QColor &color = Qt::white, const QString &text = QString::null, + QWidget *parent = 0); + ~ColorPickerItem(); + + QColor color() const; + QString text() const; + + void setSelected(bool); + bool isSelected() const; +signals: + void clicked(); + void selected(); + +public slots: + void setColor(const QColor &color, const QString &text = QString()); + +protected: + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void paintEvent(QPaintEvent *e); + +private: + QColor c; + QString t; + bool sel; +}; + +/* + +*/ +class ColorPickerPopup : public QFrame +{ + Q_OBJECT + +public: + ColorPickerPopup(int width, bool withColorDialog, + QWidget *parent = 0); + ~ColorPickerPopup(); + + void insertColor(const QColor &col, const QString &text, int index); + void exec(); + + void setExecFlag(); + + QColor lastSelected() const; + + ColorPickerItem *find(const QColor &col) const; + QColor color(int index) const; + +signals: + void selected(const QColor &); + void hid(); + +public slots: + void getColorFromDialog(); + +protected slots: + void updateSelected(); + +protected: + void keyPressEvent(QKeyEvent *e); + void showEvent(QShowEvent *e); + void hideEvent(QHideEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + + void regenerateGrid(); + +private: + QMap > widgetAt; + QList items; + QGridLayout *grid; + ColorPickerButton *moreButton; + QEventLoop *eventLoop; + + int lastPos; + int cols; + QColor lastSel; +}; + + diff --git a/code/nel/tools/3d/mesh_editor/sound_utilities.cpp b/code/nel/tools/3d/mesh_editor/sound_utilities.cpp new file mode 100644 index 000000000..d1c53601b --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/sound_utilities.cpp @@ -0,0 +1,170 @@ +// 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 +#include "sound_utilities.h" + +// STL includes + +// NeL includes +#include +#include +#include +#include +#include +#include +#include + +// Project includes +#include "configuration.h" +#include "graphics_viewport.h" + +using namespace std; +using namespace NLMISC; +using namespace NLSOUND; + +CSoundUtilities::CSoundUtilities() + : m_Configuration(NULL), + m_GraphicsViewport(NULL), + //m_LandscapeUtilities(NULL), + //m_PacsUtilities(NULL), + m_AudioMixer(NULL), + m_SoundAnimManager(NULL) +{ + +} + +CSoundUtilities::~CSoundUtilities() +{ + // release(); +} + +void CSoundUtilities::init(CConfiguration *configuration) +{ + //H_AUTO2 + nldebug("CSoundUtilities::init"); + + // copy parameters + m_Configuration = configuration; + + // check stuff we need + nlassert(m_Configuration); + + // create audiomixer + NL3D::UParticleSystemSound::setPSSound(NULL); + nlassert(!m_AudioMixer); + m_AudioMixer = UAudioMixer::createAudioMixer(); + nlassert(m_AudioMixer); + + // init audiomixer + std::vector devices; + m_AudioMixer->initDriver(m_Configuration->getValue("SoundDriver", string("Auto"))); + m_AudioMixer->getDevices(devices); + UAudioMixer::CInitInfo audioInfo; + audioInfo.AutoLoadSample = m_Configuration->getValue("SoundAutoLoadSample", true); + audioInfo.EnableOccludeObstruct = m_Configuration->getValue("SoundEnableOccludeObstruct", true); + audioInfo.EnableReverb = m_Configuration->getValue("SoundEnableReverb", true); + audioInfo.ManualRolloff = m_Configuration->getValue("SoundManualRolloff", true); + audioInfo.ForceSoftware = m_Configuration->getValue("SoundForceSoftware", false); + audioInfo.MaxTrack = m_Configuration->getValue("SoundMaxTrack", 48); + audioInfo.UseADPCM = m_Configuration->getValue("SoundUseADPCM", false); + m_AudioMixer->initDevice(m_Configuration->getValue("SoundDevice", string("")), audioInfo, NULL); + m_AudioMixer->setLowWaterMark(1); + + // config callbacks + // ... + + // sound anim manager + nlassert(!m_SoundAnimManager); + m_SoundAnimManager = new CSoundAnimManager(m_AudioMixer); + nlassert(m_SoundAnimManager); + + // temp listener pos + m_AudioMixer->setListenerPos(CVector(0.0f, 0.0f, 0.0f)); + + // init sources + // ... +} + +void CSoundUtilities::release() +{ + //H_AUTO2 + nldebug("CSoundUtilities::release"); + + // release sources + // ... + + // release sound anim manager + if (m_SoundAnimManager) + { + delete m_SoundAnimManager; + m_SoundAnimManager = NULL; + } + else nlwarning("!m_SoundAnimManager"); + + // drop config callbacks + // ... + + // release audiomixer (todo: +sources!!!) + if (m_AudioMixer) + { + delete m_AudioMixer; + m_AudioMixer = NULL; + } + else nlwarning("!m_AudioMixer"); + + // reset parameters + m_Configuration = NULL; +} + +void CSoundUtilities::updateSound() +{ + m_AudioMixer->update(); +} + +void CSoundUtilities::initGraphics(CGraphicsViewport *graphicsViewport) +{ + //H_AUTO2 + nldebug("CSoundUtilities::initGraphics"); + + // copy parameters + m_GraphicsViewport = graphicsViewport; + + // check stuff we need + nlassert(m_GraphicsViewport); + + // set particle system sound + NL3D::UParticleSystemSound::setPSSound(m_AudioMixer); + + // ... + // todo: displayers for all the test sound sources :) +} + +void CSoundUtilities::releaseGraphics() +{ + //H_AUTO2 + nldebug("CSoundUtilities::releaseGraphics"); + + // .. + + // clear particle system sound + NL3D::UParticleSystemSound::setPSSound(NULL); + + // reset parameters + m_GraphicsViewport = NULL; +} + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/sound_utilities.h b/code/nel/tools/3d/mesh_editor/sound_utilities.h new file mode 100644 index 000000000..7a94636a4 --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/sound_utilities.h @@ -0,0 +1,83 @@ +// 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 NLQT_SOUND_UTILITIES_H +#define NLQT_SOUND_UTILITIES_H +#include + +// STL includes + +// NeL includes + +// Project includes + +namespace NLSOUND { + class UAudioMixer; + class CSoundAnimManager; +} + +class CConfiguration; +class CGraphicsViewport; +//class CLandscapeUtilities; +//class CPacsUtilities; + +/** + * CSoundUtilities + * \brief CSoundUtilities + * \date 2010-02-06 12:26GMT + * \author Jan Boon (Kaetemi) + */ +class CSoundUtilities +{ +public: + CSoundUtilities(); + virtual ~CSoundUtilities(); + + void init(CConfiguration *configuration); + void release(); + + void initGraphics(CGraphicsViewport *graphicsViewport); + void releaseGraphics(); + + //void initLandscape(CLandscapeUtilities *landscapeUtilities); + //void releaseLandscape(); + + //void initPacs(CPacsUtilities *pacsUtilities); + //void releasePacs(); + + void updateSound(); + + inline NLSOUND::UAudioMixer *getAudioMixer() { return m_AudioMixer; } + inline NLSOUND::CSoundAnimManager *getSoundAnimManager() { return m_SoundAnimManager; } + +private: + CConfiguration *m_Configuration; + CGraphicsViewport *m_GraphicsViewport; + //CLandscapeUtilities *m_LandscapeUtilities; + //CPacsUtilities *m_PacsUtilities; + + NLSOUND::UAudioMixer *m_AudioMixer; + NLSOUND::CSoundAnimManager *m_SoundAnimManager; + +private: + CSoundUtilities(const CSoundUtilities &); + CSoundUtilities &operator=(const CSoundUtilities &); + +}; /* class CSoundUtilities */ + +#endif /* #ifndef NLQT_SOUND_UTILITIES_H */ + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/undo_redo_binders.cpp b/code/nel/tools/3d/mesh_editor/undo_redo_binders.cpp new file mode 100644 index 000000000..952d09ce0 --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/undo_redo_binders.cpp @@ -0,0 +1,363 @@ +// 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 +#include "undo_redo_binders.h" + +// STL includes + +// Qt includes +#include +#include +#include +#include + +// NeL includes +#include + +// Project includes +#include "qtcolorpicker.h" + +// using namespace std; +// using namespace NLMISC; + +namespace { + +int a_UndoCommandId = 9000; + +} /* anonymous namespace */ + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +CUndoRedoBinderButton::CUndoRedoBinderButton(QAbstractButton *abstractButton, QUndoStack *undoStack) + : QObject(abstractButton), m_AbstractButton(abstractButton), m_UndoStack(undoStack) +{ + nlassert(m_AbstractButton); + bool c; + m_Checked = m_AbstractButton->isChecked(); + c = connect(m_AbstractButton, SIGNAL(toggled(bool)), this, SLOT(abstractButtonToggled(bool))); + nlassertex(c, ("connect toggled(bool)")); + m_Enabled = true; +} + +CUndoRedoBinderButton::~CUndoRedoBinderButton() +{ + m_UndoStack->clear(); // may contain commands on a deleted button +} + +void CUndoRedoBinderButton::abstractButtonToggled(bool checked) +{ + if (m_Enabled) + { + if (checked != m_Checked) + { + bool undo = m_Checked; + /* bool redo = checked; */ + m_Checked = checked; /* redo; */ + m_UndoStack->push(new CUndoRedoCommandButton(this, m_AbstractButton, undo)); + } + } + else + { + m_Checked = checked; + } +} + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +CUndoRedoCommandButton::CUndoRedoCommandButton(CUndoRedoBinderButton *binder, QAbstractButton *abstractButton, bool undo/*, bool redo*/) + : QUndoCommand(), m_Binder(binder), m_AbstractButton(abstractButton), m_Undo(undo)/*, m_Redo(redo)*/ +{ + // nldebug("CUndoRedoCommandButton::CUndoRedoCommandButton()"); + nlassert(m_AbstractButton); +} + +CUndoRedoCommandButton::~CUndoRedoCommandButton() +{ + +} + +void CUndoRedoCommandButton::undo() +{ + // nldebug("CUndoRedoCommandButton::undo()"); + // nlassert(m_AbstractButton); + + m_Binder->enable(false); + if (m_AbstractButton->isChecked() != m_Undo) + m_AbstractButton->setChecked(m_Undo); + m_Binder->enable(true); +} + +void CUndoRedoCommandButton::redo() +{ + // nldebug("CUndoRedoCommandButton::redo()"); + // nlassert(m_AbstractButton); + + m_Binder->enable(false); + if (m_AbstractButton->isChecked() == m_Undo) /* != m_Redo) */ + m_AbstractButton->setChecked(!m_Undo); /* (m_Redo); */ + m_Binder->enable(true); +} + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +CUndoRedoBinderLineEdit::CUndoRedoBinderLineEdit(QLineEdit *lineEdit, QUndoStack *undoStack) + : QObject(lineEdit), m_LineEdit(lineEdit), m_UndoStack(undoStack) +{ + nlassert(m_LineEdit); + m_Id = ++a_UndoCommandId; + bool c; + m_LastValue = m_LineEdit->text(); + c = connect(m_LineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(lineEditTextChanged(const QString &))); + nlassertex(c, ("connect textChanged(const QString &)")); + m_Enabled = true; +} + +CUndoRedoBinderLineEdit::~CUndoRedoBinderLineEdit() +{ + m_UndoStack->clear(); // may contain commands on a deleted LineEdit +} + +void CUndoRedoBinderLineEdit::lineEditTextChanged(const QString &text) +{ + if (m_LineEdit->isRedoAvailable()) + { + // workaround internal undo redo of lineedit + m_LineEdit->redo(); + m_UndoStack->undo(); + return; + } + + if (m_Enabled) + { + if (text != m_LastValue) + { + QString undo = m_LastValue; + const QString &redo = text; + m_LastValue = redo; + m_UndoStack->push(new CUndoRedoCommandLineEdit(this, m_LineEdit, undo, redo, m_Id)); + } + } + else + { + m_LastValue = text; + } +} + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +CUndoRedoCommandLineEdit::CUndoRedoCommandLineEdit(CUndoRedoBinderLineEdit *binder, QLineEdit *lineEdit, const QString &undo, const QString &redo, int id) + : QUndoCommand(), m_Binder(binder), m_LineEdit(lineEdit), m_Undo(undo), m_Redo(redo), m_Id(id) +{ + // nldebug("CUndoRedoCommandLineEdit::CUndoRedoCommandLineEdit()"); + nlassert(m_LineEdit); +} + +CUndoRedoCommandLineEdit::~CUndoRedoCommandLineEdit() +{ + +} + +bool CUndoRedoCommandLineEdit::mergeWith(const QUndoCommand *other) +{ + if (m_Id != other->id()) return false; + m_Redo = static_cast(other)->m_Redo; + return true; +} + +void CUndoRedoCommandLineEdit::undo() +{ + // nldebug("CUndoRedoCommandLineEdit::undo()"); + // nlassert(m_LineEdit); + + m_Binder->enable(false); + if (m_LineEdit->text() != m_Undo) + m_LineEdit->setText(m_Undo); + m_Binder->enable(true); +} + +void CUndoRedoCommandLineEdit::redo() +{ + // nldebug("CUndoRedoCommandLineEdit::redo()"); + // nlassert(m_LineEdit); + + m_Binder->enable(false); + if (m_LineEdit->text() != m_Redo) + m_LineEdit->setText(m_Redo); + m_Binder->enable(true); +} + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +CUndoRedoBinderComboBox::CUndoRedoBinderComboBox(QComboBox *comboBox, QUndoStack *undoStack) + : QObject(comboBox), m_ComboBox(comboBox), m_UndoStack(undoStack) +{ + nlassert(m_ComboBox); + bool c; + m_LastValue = m_ComboBox->currentIndex(); + c = connect(m_ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(comboBoxCurrentIndexChanged(int))); + nlassertex(c, ("connect currentIndexChanged(int)")); + m_Enabled = true; +} + +CUndoRedoBinderComboBox::~CUndoRedoBinderComboBox() +{ + m_UndoStack->clear(); // may contain commands on a deleted ComboBox +} + +void CUndoRedoBinderComboBox::comboBoxCurrentIndexChanged(int index) +{ + if (m_Enabled) + { + if (index != m_LastValue) + { + int undo = m_LastValue; + int redo = index; + m_LastValue = redo; + m_UndoStack->push(new CUndoRedoCommandComboBox(this, m_ComboBox, undo, redo)); + } + } + else + { + m_LastValue = index; + } +} + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +CUndoRedoCommandComboBox::CUndoRedoCommandComboBox(CUndoRedoBinderComboBox *binder, QComboBox *comboBox, int undo, int redo) + : QUndoCommand(), m_Binder(binder), m_ComboBox(comboBox), m_Undo(undo), m_Redo(redo) +{ + // nldebug("CUndoRedoCommandComboBox::CUndoRedoCommandComboBox()"); + nlassert(m_ComboBox); +} + +CUndoRedoCommandComboBox::~CUndoRedoCommandComboBox() +{ + +} + +void CUndoRedoCommandComboBox::undo() +{ + // nldebug("CUndoRedoCommandComboBox::undo()"); + // nlassert(m_ComboBox); + + m_Binder->enable(false); + if (m_ComboBox->currentIndex() != m_Undo) + m_ComboBox->setCurrentIndex(m_Undo); + m_Binder->enable(true); +} + +void CUndoRedoCommandComboBox::redo() +{ + // nldebug("CUndoRedoCommandComboBox::redo()"); + // nlassert(m_ComboBox); + + m_Binder->enable(false); + if (m_ComboBox->currentIndex() != m_Redo) + m_ComboBox->setCurrentIndex(m_Redo); + m_Binder->enable(true); +} + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +CUndoRedoBinderColorPicker::CUndoRedoBinderColorPicker(QtColorPicker *colorPicker, QUndoStack *undoStack) + : QObject(colorPicker), m_ColorPicker(colorPicker), m_UndoStack(undoStack) +{ + nlassert(m_ColorPicker); + bool c; + m_LastValue = m_ColorPicker->currentColor(); + c = connect(m_ColorPicker, SIGNAL(colorChanged(const QColor &)), this, SLOT(colorPickerColorChanged(const QColor &))); + nlassertex(c, ("connect colorChanged(const QColor &)")); + m_Enabled = true; +} + +CUndoRedoBinderColorPicker::~CUndoRedoBinderColorPicker() +{ + m_UndoStack->clear(); // may contain commands on a deleted ColorPicker +} + +void CUndoRedoBinderColorPicker::colorPickerColorChanged(const QColor &col) +{ + if (m_Enabled) + { + if (col != m_LastValue) + { + QColor undo = m_LastValue; + const QColor &redo = col; + m_LastValue = redo; + m_UndoStack->push(new CUndoRedoCommandColorPicker(this, m_ColorPicker, undo, redo)); + } + } + else + { + m_LastValue = col; + } +} + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +CUndoRedoCommandColorPicker::CUndoRedoCommandColorPicker(CUndoRedoBinderColorPicker *binder, QtColorPicker *colorPicker, const QColor &undo, const QColor &redo) + : QUndoCommand(), m_Binder(binder), m_ColorPicker(colorPicker), m_Undo(undo), m_Redo(redo) +{ + // nldebug("CUndoRedoCommandColorPicker::CUndoRedoCommandColorPicker()"); + nlassert(m_ColorPicker); +} + +CUndoRedoCommandColorPicker::~CUndoRedoCommandColorPicker() +{ + +} + +void CUndoRedoCommandColorPicker::undo() +{ + // nldebug("CUndoRedoCommandColorPicker::undo()"); + // nlassert(m_ColorPicker); + + m_Binder->enable(false); + if (m_ColorPicker->currentColor() != m_Undo) + m_ColorPicker->setCurrentColor(m_Undo); + m_Binder->enable(true); +} + +void CUndoRedoCommandColorPicker::redo() +{ + // nldebug("CUndoRedoCommandColorPicker::redo()"); + // nlassert(m_ColorPicker); + + m_Binder->enable(false); + if (m_ColorPicker->currentColor() != m_Redo) + m_ColorPicker->setCurrentColor(m_Redo); + m_Binder->enable(true); +} + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +/* end of file */ diff --git a/code/nel/tools/3d/mesh_editor/undo_redo_binders.h b/code/nel/tools/3d/mesh_editor/undo_redo_binders.h new file mode 100644 index 000000000..d9fe78721 --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/undo_redo_binders.h @@ -0,0 +1,314 @@ +// 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 NLQT_UNDO_REDO_BINDERS_H +#define NLQT_UNDO_REDO_BINDERS_H +#include + +// STL includes + +// Qt includes +#include +#include +#include +#include + +// NeL includes + +// Project includes + +class QUndoStack; +class QAbstractButton; +class QLineEdit; +class QComboBox; +class QtColorPicker; + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +/** + * CUndoRedoBinderButton + * \brief CUndoRedoBinderButton + * \date 2010-02-13 14:02GMT + * \author Jan Boon (Kaetemi) + */ +class CUndoRedoBinderButton : public QObject +{ + Q_OBJECT + +public: + CUndoRedoBinderButton(QAbstractButton *abstractButton, QUndoStack *undoStack); + virtual ~CUndoRedoBinderButton(); + + inline void enable(bool enabled) { m_Enabled = enabled; } + +private slots: + void abstractButtonToggled(bool checked); + +private: + bool m_Enabled; // binder enabled + bool m_Checked; + QAbstractButton *m_AbstractButton; + QUndoStack *m_UndoStack; + +private: + CUndoRedoBinderButton(const CUndoRedoBinderButton &); + CUndoRedoBinderButton &operator=(const CUndoRedoBinderButton &); + +}; /* class CUndoRedoBinderButton */ + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +/** + * CUndoRedoCommandButton + * \brief CUndoRedoCommandButton + * \date 2010-02-13 14:02GMT + * \author Jan Boon (Kaetemi) + */ +class CUndoRedoCommandButton : public QUndoCommand +{ +public: + CUndoRedoCommandButton(CUndoRedoBinderButton *binder, QAbstractButton *abstractButton, bool undo/*, bool redo*/); + virtual ~CUndoRedoCommandButton(); + + virtual void undo(); + virtual void redo(); + +private: + bool m_Undo; + /*bool m_Redo;*/ + CUndoRedoBinderButton *m_Binder; + QAbstractButton *m_AbstractButton; + QUndoStack *m_UndoStack; + +private: + CUndoRedoCommandButton(const CUndoRedoCommandButton &); + CUndoRedoCommandButton &operator=(const CUndoRedoCommandButton &); + +}; /* class CUndoRedoCommandButton */ + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +/** + * CUndoRedoBinderLineEdit + * \brief CUndoRedoBinderLineEdit + * \date 2010-02-13 14:02GMT + * \author Jan Boon (Kaetemi) + */ +class CUndoRedoBinderLineEdit : public QObject +{ + Q_OBJECT + +public: + CUndoRedoBinderLineEdit(QLineEdit *lineEdit, QUndoStack *undoStack); + virtual ~CUndoRedoBinderLineEdit(); + + inline void enable(bool enabled) { m_Enabled = enabled; } + +private slots: + void lineEditTextChanged(const QString &text); + +private: + bool m_Enabled; // binder enabled + QString m_LastValue; + QLineEdit *m_LineEdit; + QUndoStack *m_UndoStack; + int m_Id; + +private: + CUndoRedoBinderLineEdit(const CUndoRedoBinderLineEdit &); + CUndoRedoBinderLineEdit &operator=(const CUndoRedoBinderLineEdit &); + +}; /* class CUndoRedoBinderLineEdit */ + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +/** + * CUndoRedoCommandLineEdit + * \brief CUndoRedoCommandLineEdit + * \date 2010-02-13 14:02GMT + * \author Jan Boon (Kaetemi) + */ +class CUndoRedoCommandLineEdit : public QUndoCommand +{ +public: + CUndoRedoCommandLineEdit(CUndoRedoBinderLineEdit *binder, QLineEdit *abtractLineEdit, const QString &undo, const QString &redo, int id); + virtual ~CUndoRedoCommandLineEdit(); + + virtual void undo(); + virtual void redo(); + + virtual int id() const { return m_Id; }; + virtual bool mergeWith(const QUndoCommand *other); + +private: + QString m_Undo; + QString m_Redo; + CUndoRedoBinderLineEdit *m_Binder; + QLineEdit *m_LineEdit; + QUndoStack *m_UndoStack; + int m_Id; + +private: + CUndoRedoCommandLineEdit(const CUndoRedoCommandLineEdit &); + CUndoRedoCommandLineEdit &operator=(const CUndoRedoCommandLineEdit &); + +}; /* class CUndoRedoCommandLineEdit */ + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +/** + * CUndoRedoBinderComboBox + * \brief CUndoRedoBinderComboBox + * \date 2010-02-13 14:02GMT + * \author Jan Boon (Kaetemi) + */ +class CUndoRedoBinderComboBox : public QObject +{ + Q_OBJECT + +public: + CUndoRedoBinderComboBox(QComboBox *comboBox, QUndoStack *undoStack); + virtual ~CUndoRedoBinderComboBox(); + + inline void enable(bool enabled) { m_Enabled = enabled; } + +private slots: + void comboBoxCurrentIndexChanged(int index); + +private: + bool m_Enabled; // binder enabled + int m_LastValue; + QComboBox *m_ComboBox; + QUndoStack *m_UndoStack; + +private: + CUndoRedoBinderComboBox(const CUndoRedoBinderComboBox &); + CUndoRedoBinderComboBox &operator=(const CUndoRedoBinderComboBox &); + +}; /* class CUndoRedoBinderComboBox */ + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +/** + * CUndoRedoCommandComboBox + * \brief CUndoRedoCommandComboBox + * \date 2010-02-13 14:02GMT + * \author Jan Boon (Kaetemi) + */ +class CUndoRedoCommandComboBox : public QUndoCommand +{ +public: + CUndoRedoCommandComboBox(CUndoRedoBinderComboBox *binder, QComboBox *abtractComboBox, int undo, int redo); + virtual ~CUndoRedoCommandComboBox(); + + virtual void undo(); + virtual void redo(); + +private: + int m_Undo; + int m_Redo; + CUndoRedoBinderComboBox *m_Binder; + QComboBox *m_ComboBox; + QUndoStack *m_UndoStack; + +private: + CUndoRedoCommandComboBox(const CUndoRedoCommandComboBox &); + CUndoRedoCommandComboBox &operator=(const CUndoRedoCommandComboBox &); + +}; /* class CUndoRedoCommandComboBox */ + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +/** + * CUndoRedoBinderColorPicker + * \brief CUndoRedoBinderColorPicker + * \date 2010-02-13 14:02GMT + * \author Jan Boon (Kaetemi) + */ +class CUndoRedoBinderColorPicker : public QObject +{ + Q_OBJECT + +public: + CUndoRedoBinderColorPicker(QtColorPicker *colorPicker, QUndoStack *undoStack); + virtual ~CUndoRedoBinderColorPicker(); + + inline void enable(bool enabled) { m_Enabled = enabled; } + +private slots: + void colorPickerColorChanged(const QColor &col); + +private: + bool m_Enabled; // binder enabled + QColor m_LastValue; + QtColorPicker *m_ColorPicker; + QUndoStack *m_UndoStack; + +private: + CUndoRedoBinderColorPicker(const CUndoRedoBinderColorPicker &); + CUndoRedoBinderColorPicker &operator=(const CUndoRedoBinderColorPicker &); + +}; /* class CUndoRedoBinderColorPicker */ + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +/** + * CUndoRedoCommandColorPicker + * \brief CUndoRedoCommandColorPicker + * \date 2010-02-13 14:02GMT + * \author Jan Boon (Kaetemi) + */ +class CUndoRedoCommandColorPicker : public QUndoCommand +{ +public: + CUndoRedoCommandColorPicker(CUndoRedoBinderColorPicker *binder, QtColorPicker *abtractColorPicker, const QColor &undo, const QColor &redo); + virtual ~CUndoRedoCommandColorPicker(); + + virtual void undo(); + virtual void redo(); + +private: + QColor m_Undo; + QColor m_Redo; + CUndoRedoBinderColorPicker *m_Binder; + QtColorPicker *m_ColorPicker; + QUndoStack *m_UndoStack; + +private: + CUndoRedoCommandColorPicker(const CUndoRedoCommandColorPicker &); + CUndoRedoCommandColorPicker &operator=(const CUndoRedoCommandColorPicker &); + +}; /* class CUndoRedoCommandColorPicker */ + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +#endif /* #ifndef NLQT_UNDO_REDO_BINDERS_H */ + +/* end of file */ diff --git a/code/nel/tools/3d/shared_widgets/command_log.cpp b/code/nel/tools/3d/shared_widgets/command_log.cpp index fda28dd2a..9ce23e225 100644 --- a/code/nel/tools/3d/shared_widgets/command_log.cpp +++ b/code/nel/tools/3d/shared_widgets/command_log.cpp @@ -60,8 +60,8 @@ CCommandLog::CCommandLog(QWidget *parent) : QWidget(parent) layout->addWidget(m_CommandInput); setLayout(layout); - connect(m_CommandInput, SIGNAL(returnPressed()), this, SLOT(returnPressed())); - connect(this, SIGNAL(tSigDisplay(const QColor &, const QString &)), this, SLOT(tSlotDisplay(const QColor &, const QString &))); + connect(m_CommandInput, SIGNAL(returnPressed()), this, SLOT(returnPressed()), Qt::QueuedConnection); + connect(this, SIGNAL(tSigDisplay(const QColor &, const QString &)), this, SLOT(tSlotDisplay(const QColor &, const QString &)), Qt::QueuedConnection); } @@ -123,7 +123,7 @@ void CCommandLog::returnPressed() CCommandLogDisplayer::CCommandLogDisplayer(QWidget *parent) : CCommandLog(parent) { - connect(this, SIGNAL(execCommand(const std::string &)), this, SLOT(execCommandLog(const std::string &))); + connect(this, SIGNAL(execCommand(const QString &)), this, SLOT(execCommandLog(const QString &)), Qt::QueuedConnection); DebugLog->addDisplayer(this); InfoLog->addDisplayer(this); WarningLog->addDisplayer(this); diff --git a/code/nel/tools/3d/shared_widgets/common.h b/code/nel/tools/3d/shared_widgets/common.h index 23cb2b86d..d4ad92ffb 100644 --- a/code/nel/tools/3d/shared_widgets/common.h +++ b/code/nel/tools/3d/shared_widgets/common.h @@ -48,16 +48,21 @@ namespace { void preApplication() { - QCoreApplication::libraryPaths(); - QString app_location = QCoreApplication::applicationFilePath(); - app_location.truncate(app_location.lastIndexOf(QLatin1Char('/'))); - app_location = QDir(app_location).canonicalPath(); - QCoreApplication::removeLibraryPath(app_location); - QCoreApplication::addLibraryPath("./platforms"); - QCoreApplication::addLibraryPath("./qtwebengine"); - QCoreApplication::addLibraryPath("./imageformats"); - QCoreApplication::addLibraryPath("./iconengines"); - QCoreApplication::addLibraryPath("./designer"); + char *qpa = getenv("QT_QPA_PLATFORM_PLUGIN_PATH"); + if (qpa && qpa[0]) + { + // Trick to avoid Qt attempting to load up every file in the application path as Qt plugin, speeds up debug startup + QCoreApplication::libraryPaths(); + QString app_location = QCoreApplication::applicationFilePath(); + app_location.truncate(app_location.lastIndexOf(QLatin1Char('/'))); + app_location = QDir(app_location).canonicalPath(); + QCoreApplication::removeLibraryPath(app_location); + QCoreApplication::addLibraryPath("./platforms"); + QCoreApplication::addLibraryPath("./qtwebengine"); + QCoreApplication::addLibraryPath("./imageformats"); + QCoreApplication::addLibraryPath("./iconengines"); + QCoreApplication::addLibraryPath("./designer"); + } } void postApplication()