Forgot to add directory

actorid
scrawl 12 years ago
parent 062ff189a2
commit d6e9cb114e

@ -0,0 +1,195 @@
#include "Actions.hpp"
#include "../Main/Factory.hpp"
namespace sh
{
void ActionDeleteMaterial::execute()
{
sh::Factory::getInstance().destroyMaterialInstance(mName);
}
void ActionCloneMaterial::execute()
{
sh::MaterialInstance* sourceMaterial = sh::Factory::getInstance().getMaterialInstance(mSourceName);
std::string sourceMaterialParent = static_cast<sh::MaterialInstance*>(sourceMaterial->getParent())->getName();
sh::MaterialInstance* material = sh::Factory::getInstance().createMaterialInstance(
mDestName, sourceMaterialParent);
sourceMaterial->copyAll(material, sourceMaterial, false);
material->setSourceFile(sourceMaterial->getSourceFile());
}
void ActionSaveAll::execute()
{
sh::Factory::getInstance().saveAll();
}
void ActionChangeGlobalSetting::execute()
{
sh::Factory::getInstance().setGlobalSetting(mName, mNewValue);
}
void ActionCreateConfiguration::execute()
{
sh::Configuration newConfiguration;
sh::Factory::getInstance().createConfiguration(mName);
}
void ActionDeleteConfiguration::execute()
{
sh::Factory::getInstance().destroyConfiguration(mName);
}
void ActionChangeConfiguration::execute()
{
sh::Configuration* c = sh::Factory::getInstance().getConfiguration(mName);
c->setProperty(mKey, sh::makeProperty(new sh::StringValue(mValue)));
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionDeleteConfigurationProperty::execute()
{
sh::Configuration* c = sh::Factory::getInstance().getConfiguration(mName);
c->deleteProperty(mKey);
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionSetMaterialProperty::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
m->setProperty(mKey, sh::makeProperty(mValue));
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionDeleteMaterialProperty::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
m->deleteProperty(mKey);
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionCreatePass::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
m->createPass();
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionDeletePass::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
m->deletePass(mPassIndex);
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionSetPassProperty::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
assert (m->getPasses()->size() > mPassIndex);
m->getPasses()->at(mPassIndex).setProperty (mKey, sh::makeProperty(mValue));
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionDeletePassProperty::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
assert (m->getPasses()->size() > mPassIndex);
m->getPasses()->at(mPassIndex).deleteProperty(mKey);
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionSetShaderProperty::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
assert (m->getPasses()->size() > mPassIndex);
m->getPasses()->at(mPassIndex).mShaderProperties.setProperty (mKey, sh::makeProperty(mValue));
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionDeleteShaderProperty::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
assert (m->getPasses()->size() > mPassIndex);
m->getPasses()->at(mPassIndex).mShaderProperties.deleteProperty (mKey);
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionSetTextureProperty::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
assert (m->getPasses()->size() > mPassIndex);
assert (m->getPasses()->at(mPassIndex).mTexUnits.size() > mTextureIndex);
m->getPasses()->at(mPassIndex).mTexUnits.at(mTextureIndex).setProperty(mKey, sh::makeProperty(mValue));
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionDeleteTextureProperty::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
assert (m->getPasses()->size() > mPassIndex);
assert (m->getPasses()->at(mPassIndex).mTexUnits.size() > mTextureIndex);
m->getPasses()->at(mPassIndex).mTexUnits.at(mTextureIndex).deleteProperty(mKey);
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionCreateTextureUnit::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
assert (m->getPasses()->size() > mPassIndex);
m->getPasses()->at(mPassIndex).createTextureUnit(mTexUnitName);
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionDeleteTextureUnit::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
assert (m->getPasses()->size() > mPassIndex);
assert (m->getPasses()->at(mPassIndex).mTexUnits.size() > mTextureIndex);
m->getPasses()->at(mPassIndex).mTexUnits.erase(m->getPasses()->at(mPassIndex).mTexUnits.begin() + mTextureIndex);
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionMoveTextureUnit::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
assert (m->getPasses()->size() > mPassIndex);
assert (m->getPasses()->at(mPassIndex).mTexUnits.size() > mTextureIndex);
if (!mMoveUp)
assert (m->getPasses()->at(mPassIndex).mTexUnits.size() > mTextureIndex+1);
std::vector<MaterialInstanceTextureUnit> textures = m->getPasses()->at(mPassIndex).mTexUnits;
if (mMoveUp)
std::swap(textures[mTextureIndex-1], textures[mTextureIndex]);
else
std::swap(textures[mTextureIndex+1], textures[mTextureIndex]);
m->getPasses()->at(mPassIndex).mTexUnits = textures;
sh::Factory::getInstance().notifyConfigurationChanged();
}
void ActionChangeTextureUnitName::execute()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
assert (m->getPasses()->size() > mPassIndex);
assert (m->getPasses()->at(mPassIndex).mTexUnits.size() > mTextureIndex);
m->getPasses()->at(mPassIndex).mTexUnits[mTextureIndex].setName(mTexUnitName);
sh::Factory::getInstance().notifyConfigurationChanged();
}
}

@ -0,0 +1,307 @@
#ifndef SH_ACTIONS_H
#define SH_ACTIONS_H
#include <string>
namespace sh
{
class Action
{
public:
virtual void execute() = 0;
virtual ~Action();
};
class ActionDeleteMaterial : public Action
{
public:
ActionDeleteMaterial(const std::string& name)
: mName(name) {}
virtual void execute();
private:
std::string mName;
};
class ActionCloneMaterial : public Action
{
public:
ActionCloneMaterial(const std::string& sourceName, const std::string& destName)
: mSourceName(sourceName), mDestName(destName) {}
virtual void execute();
private:
std::string mSourceName;
std::string mDestName;
};
class ActionSaveAll : public Action
{
public:
virtual void execute();
};
class ActionChangeGlobalSetting : public Action
{
public:
ActionChangeGlobalSetting(const std::string& name, const std::string& newValue)
: mName(name), mNewValue(newValue) {}
virtual void execute();
private:
std::string mName;
std::string mNewValue;
};
// configuration
class ActionCreateConfiguration : public Action
{
public:
ActionCreateConfiguration(const std::string& name)
: mName(name) {}
virtual void execute();
private:
std::string mName;
};
class ActionDeleteConfiguration : public Action
{
public:
ActionDeleteConfiguration(const std::string& name)
: mName(name) {}
virtual void execute();
private:
std::string mName;
};
class ActionChangeConfiguration : public Action
{
public:
ActionChangeConfiguration (const std::string& name, const std::string& key, const std::string& value)
: mName(name), mKey(key), mValue(value) {}
virtual void execute();
private:
std::string mName;
std::string mKey;
std::string mValue;
};
class ActionDeleteConfigurationProperty : public Action
{
public:
ActionDeleteConfigurationProperty (const std::string& name, const std::string& key)
: mName(name), mKey(key) {}
virtual void execute();
private:
std::string mName;
std::string mKey;
};
// material
class ActionSetMaterialProperty : public Action
{
public:
ActionSetMaterialProperty (const std::string& name, const std::string& key, const std::string& value)
: mName(name), mKey(key), mValue(value) {}
virtual void execute();
private:
std::string mName;
std::string mKey;
std::string mValue;
};
class ActionDeleteMaterialProperty : public Action
{
public:
ActionDeleteMaterialProperty (const std::string& name, const std::string& key)
: mName(name), mKey(key) {}
virtual void execute();
private:
std::string mName;
std::string mKey;
};
// pass
class ActionCreatePass : public Action
{
public:
ActionCreatePass (const std::string& name)
: mName(name) {}
virtual void execute();
private:
std::string mName;
};
class ActionDeletePass : public Action
{
public:
ActionDeletePass (const std::string& name, int passIndex)
: mName(name), mPassIndex(passIndex) {}
virtual void execute();
private:
std::string mName;
int mPassIndex;
};
class ActionSetPassProperty : public Action
{
public:
ActionSetPassProperty (const std::string& name, int passIndex, const std::string& key, const std::string& value)
: mName(name), mPassIndex(passIndex), mKey(key), mValue(value) {}
virtual void execute();
private:
std::string mName;
int mPassIndex;
std::string mKey;
std::string mValue;
};
class ActionDeletePassProperty : public Action
{
public:
ActionDeletePassProperty (const std::string& name, int passIndex, const std::string& key)
: mName(name), mPassIndex(passIndex), mKey(key) {}
virtual void execute();
private:
std::string mName;
int mPassIndex;
std::string mKey;
};
// shader
class ActionSetShaderProperty : public Action
{
public:
ActionSetShaderProperty (const std::string& name, int passIndex, const std::string& key, const std::string& value)
: mName(name), mPassIndex(passIndex), mKey(key), mValue(value) {}
virtual void execute();
private:
std::string mName;
int mPassIndex;
std::string mKey;
std::string mValue;
};
class ActionDeleteShaderProperty : public Action
{
public:
ActionDeleteShaderProperty (const std::string& name, int passIndex, const std::string& key)
: mName(name), mPassIndex(passIndex), mKey(key) {}
virtual void execute();
private:
std::string mName;
int mPassIndex;
std::string mKey;
};
// texture unit
class ActionChangeTextureUnitName : public Action
{
public:
ActionChangeTextureUnitName (const std::string& name, int passIndex, int textureIndex, const std::string& texUnitName)
: mName(name), mPassIndex(passIndex), mTextureIndex(textureIndex), mTexUnitName(texUnitName) {}
virtual void execute();
private:
std::string mName;
int mPassIndex;
int mTextureIndex;
std::string mTexUnitName;
};
class ActionCreateTextureUnit : public Action
{
public:
ActionCreateTextureUnit (const std::string& name, int passIndex, const std::string& texUnitName)
: mName(name), mPassIndex(passIndex), mTexUnitName(texUnitName) {}
virtual void execute();
private:
std::string mName;
int mPassIndex;
std::string mTexUnitName;
};
class ActionDeleteTextureUnit : public Action
{
public:
ActionDeleteTextureUnit (const std::string& name, int passIndex, int textureIndex)
: mName(name), mPassIndex(passIndex), mTextureIndex(textureIndex) {}
virtual void execute();
private:
std::string mName;
int mPassIndex;
int mTextureIndex;
};
class ActionMoveTextureUnit : public Action
{
public:
ActionMoveTextureUnit (const std::string& name, int passIndex, int textureIndex, bool moveUp)
: mName(name), mPassIndex(passIndex), mTextureIndex(textureIndex), mMoveUp(moveUp) {}
virtual void execute();
private:
std::string mName;
int mPassIndex;
int mTextureIndex;
bool mMoveUp;
};
class ActionSetTextureProperty : public Action
{
public:
ActionSetTextureProperty (const std::string& name, int passIndex, int textureIndex, const std::string& key, const std::string& value)
: mName(name), mPassIndex(passIndex), mTextureIndex(textureIndex), mKey(key), mValue(value) {}
virtual void execute();
private:
std::string mName;
int mPassIndex;
int mTextureIndex;
std::string mKey;
std::string mValue;
};
class ActionDeleteTextureProperty : public Action
{
public:
ActionDeleteTextureProperty (const std::string& name, int passIndex, int textureIndex, const std::string& key)
: mName(name), mPassIndex(passIndex), mTextureIndex(textureIndex), mKey(key) {}
virtual void execute();
private:
std::string mName;
int mPassIndex;
int mTextureIndex;
std::string mKey;
};
}
#endif

@ -0,0 +1,31 @@
#include "AddPropertyDialog.hpp"
#include "ui_addpropertydialog.h"
AddPropertyDialog::AddPropertyDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::AddPropertyDialog)
, mType(0)
{
ui->setupUi(this);
connect(ui->buttonBox, SIGNAL(accepted()),
this, SLOT(accepted()));
connect(ui->buttonBox, SIGNAL(rejected()),
this, SLOT(rejected()));
}
void AddPropertyDialog::accepted()
{
mName = ui->lineEdit->text();
mType = ui->comboBox->currentIndex();
}
void AddPropertyDialog::rejected()
{
mName = "";
}
AddPropertyDialog::~AddPropertyDialog()
{
delete ui;
}

@ -0,0 +1,22 @@
#ifndef ADDPROPERTYDIALOG_H
#define ADDPROPERTYDIALOG_H
#include <QDialog>
namespace Ui {
class AddPropertyDialog;
}
class AddPropertyDialog : public QDialog
{
Q_OBJECT
public:
explicit AddPropertyDialog(QWidget *parent = 0);
~AddPropertyDialog();
private:
Ui::AddPropertyDialog *ui;
};
#endif // ADDPROPERTYDIALOG_H

@ -0,0 +1,29 @@
#ifndef ADDPROPERTYDIALOG_H
#define ADDPROPERTYDIALOG_H
#include <QDialog>
namespace Ui {
class AddPropertyDialog;
}
class AddPropertyDialog : public QDialog
{
Q_OBJECT
public:
explicit AddPropertyDialog(QWidget *parent = 0);
~AddPropertyDialog();
int mType;
QString mName;
public slots:
void accepted();
void rejected();
private:
Ui::AddPropertyDialog *ui;
};
#endif // ADDPROPERTYDIALOG_H

@ -0,0 +1,61 @@
set(SHINY_EDITOR_LIBRARY "shiny.Editor")
find_package(Qt4)
if (QT_FOUND)
add_definitions(-DSHINY_BUILD_MATERIAL_EDITOR=1)
set (SHINY_BUILD_EDITOR_FLAG -DSHINY_BUILD_MATERIAL_EDITOR=1 PARENT_SCOPE)
set(QT_USE_QTGUI 1)
# Headers that must be preprocessed
set(SHINY_EDITOR_HEADER_MOC
MainWindow.hpp
NewMaterialDialog.hpp
AddPropertyDialog.hpp
PropertySortModel.hpp
)
set(SHINY_EDITOR_UI
mainwindow.ui
newmaterialdialog.ui
addpropertydialog.ui
)
QT4_WRAP_CPP(MOC_SRCS ${SHINY_EDITOR_HEADER_MOC})
QT4_WRAP_UI(UI_HDRS ${SHINY_EDITOR_UI})
set(SOURCE_FILES
NewMaterialDialog.cpp
AddPropertyDialog.cpp
ColoredTabWidget.hpp
MainWindow.cpp
Editor.cpp
Actions.cpp
Query.cpp
PropertySortModel.cpp
${SHINY_EDITOR_UI} # Just to have them in the IDE's file explorer
)
include(${QT_USE_FILE})
set (CMAKE_INCLUDE_CURRENT_DIR "true")
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_library(${SHINY_EDITOR_LIBRARY} STATIC ${SOURCE_FILES} ${MOC_SRCS} ${UI_HDRS})
set(SHINY_LIBRARIES ${SHINY_LIBRARIES}
${SHINY_EDITOR_LIBRARY}
${QT_LIBRARIES}
)
set(SHINY_LIBRARIES ${SHINY_LIBRARIES} PARENT_SCOPE)
else (QT_FOUND)
add_definitions(-DSHINY_BUILD_MATERIAL_EDITOR=0)
set (SHINY_BUILD_EDITOR_FLAG -DSHINY_BUILD_MATERIAL_EDITOR=0 PARENT_SCOPE)
message(STATUS "QT4 was not found. You will not be able to use the material editor.")
endif(QT_FOUND)

@ -0,0 +1,24 @@
#ifndef SHINY_EDITOR_COLOREDTABWIDGET_H
#define SHINY_EDITOR_COLOREDTABWIDGET_H
#include <QTabWidget>
namespace sh
{
/// Makes tabBar() public to allow changing tab title colors.
class ColoredTabWidget : public QTabWidget
{
public:
ColoredTabWidget(QWidget* parent = 0)
: QTabWidget(parent) {}
QTabBar* tabBar()
{
return QTabWidget::tabBar();
}
};
}
#endif

@ -0,0 +1,117 @@
#include "Editor.hpp"
#include <QApplication>
#include <QTimer>
#include <boost/thread.hpp>
#include "../Main/Factory.hpp"
#include "MainWindow.hpp"
namespace sh
{
Editor::Editor()
: mMainWindow(NULL)
, mApplication(NULL)
, mInitialized(false)
, mThread(NULL)
{
}
Editor::~Editor()
{
if (mMainWindow)
mMainWindow->mRequestExit = true;
if (mThread)
mThread->join();
delete mThread;
}
void Editor::show()
{
if (!mInitialized)
{
mInitialized = true;
mThread = new boost::thread(boost::bind(&Editor::runThread, this));
}
else
{
if (mMainWindow)
mMainWindow->mRequestShowWindow = true;
}
}
void Editor::runThread()
{
int argc = 0;
char** argv = NULL;
mApplication = new QApplication(argc, argv);
mApplication->setQuitOnLastWindowClosed(false);
mMainWindow = new MainWindow();
mMainWindow->mSync = &mSync;
mMainWindow->show();
mApplication->exec();
delete mApplication;
}
void Editor::update()
{
sh::Factory::getInstance().doMonitorShaderFiles();
if (!mMainWindow)
return;
{
boost::mutex::scoped_lock lock(mSync.mActionMutex);
// execute pending actions
while (mMainWindow->mActionQueue.size())
{
Action* action = mMainWindow->mActionQueue.front();
action->execute();
delete action;
mMainWindow->mActionQueue.pop();
}
}
{
boost::mutex::scoped_lock lock(mSync.mQueryMutex);
// execute pending queries
for (std::vector<Query*>::iterator it = mMainWindow->mQueries.begin(); it != mMainWindow->mQueries.end(); ++it)
{
Query* query = *it;
if (!query->mDone)
query->execute();
}
}
boost::mutex::scoped_lock lock2(mSync.mUpdateMutex);
// update the list of materials
mMainWindow->mState.mMaterialList.clear();
sh::Factory::getInstance().listMaterials(mMainWindow->mState.mMaterialList);
// update global settings
mMainWindow->mState.mGlobalSettingsMap.clear();
sh::Factory::getInstance().listGlobalSettings(mMainWindow->mState.mGlobalSettingsMap);
// update configuration list
mMainWindow->mState.mConfigurationList.clear();
sh::Factory::getInstance().listConfigurationNames(mMainWindow->mState.mConfigurationList);
// update shader list
mMainWindow->mState.mShaderSets.clear();
sh::Factory::getInstance().listShaderSets(mMainWindow->mState.mShaderSets);
mMainWindow->mState.mErrors += sh::Factory::getInstance().getErrorLog();
}
}

@ -0,0 +1,73 @@
#ifndef SH_EDITOR_H
#define SH_EDITOR_H
#if SHINY_BUILD_MATERIAL_EDITOR
class QApplication;
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
namespace boost
{
class thread;
}
namespace sh
{
class MainWindow;
struct SynchronizationState
{
boost::mutex mUpdateMutex;
boost::mutex mActionMutex;
boost::mutex mQueryMutex;
};
class Editor
{
public:
Editor();
~Editor();
void show();
void update();
private:
bool mInitialized;
MainWindow* mMainWindow;
QApplication* mApplication;
SynchronizationState mSync;
boost::thread* mThread;
void runThread();
void processShowWindow();
};
}
#else
// Dummy implementation, so that the user's code does not have to be polluted with #ifdefs
namespace sh
{
class Editor
{
public:
Editor() {}
~Editor() {}
void show() {}
void update() {}
};
}
#endif
#endif

@ -0,0 +1,950 @@
#include "MainWindow.hpp"
#include "ui_mainwindow.h"
#include <QCloseEvent>
#include <QTimer>
#include <QInputDialog>
#include <QMessageBox>
#include "Editor.hpp"
#include "ColoredTabWidget.hpp"
#include "AddPropertyDialog.hpp"
sh::MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, mRequestShowWindow(false)
, mRequestExit(false)
, mIgnoreGlobalSettingChange(false)
, mIgnoreConfigurationChange(false)
, mIgnoreMaterialChange(false)
, mIgnoreMaterialPropertyChange(false)
{
ui->setupUi(this);
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(onIdle()));
timer->start(50);
QList<int> sizes;
sizes << 250;
sizes << 550;
ui->splitter->setSizes(sizes);
mMaterialModel = new QStringListModel(this);
mMaterialProxyModel = new QSortFilterProxyModel(this);
mMaterialProxyModel->setSourceModel(mMaterialModel);
mMaterialProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
mMaterialProxyModel->setDynamicSortFilter(true);
mMaterialProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
ui->materialList->setModel(mMaterialProxyModel);
ui->materialList->setSelectionMode(QAbstractItemView::SingleSelection);
ui->materialList->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->materialList->setAlternatingRowColors(true);
connect(ui->materialList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
this, SLOT(onMaterialSelectionChanged(QModelIndex,QModelIndex)));
mMaterialPropertyModel = new QStandardItemModel(0, 2, this);
mMaterialPropertyModel->setHorizontalHeaderItem(0, new QStandardItem(QString("Name")));
mMaterialPropertyModel->setHorizontalHeaderItem(1, new QStandardItem(QString("Value")));
connect(mMaterialPropertyModel, SIGNAL(itemChanged(QStandardItem*)),
this, SLOT(onMaterialPropertyChanged(QStandardItem*)));
mMaterialSortModel = new PropertySortModel(this);
mMaterialSortModel->setSourceModel(mMaterialPropertyModel);
mMaterialSortModel->setDynamicSortFilter(true);
mMaterialSortModel->setSortCaseSensitivity(Qt::CaseInsensitive);
ui->materialView->setModel(mMaterialSortModel);
ui->materialView->setContextMenuPolicy(Qt::CustomContextMenu);
ui->materialView->setAlternatingRowColors(true);
ui->materialView->setSortingEnabled(true);
connect(ui->materialView, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(onContextMenuRequested(QPoint)));
mGlobalSettingsModel = new QStandardItemModel(0, 2, this);
mGlobalSettingsModel->setHorizontalHeaderItem(0, new QStandardItem(QString("Name")));
mGlobalSettingsModel->setHorizontalHeaderItem(1, new QStandardItem(QString("Value")));
connect(mGlobalSettingsModel, SIGNAL(itemChanged(QStandardItem*)),
this, SLOT(onGlobalSettingChanged(QStandardItem*)));
ui->globalSettingsView->setModel(mGlobalSettingsModel);
ui->globalSettingsView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
ui->globalSettingsView->verticalHeader()->hide();
ui->globalSettingsView->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
ui->globalSettingsView->setSelectionMode(QAbstractItemView::SingleSelection);
ui->configurationList->setSelectionMode(QAbstractItemView::SingleSelection);
ui->configurationList->setEditTriggers(QAbstractItemView::NoEditTriggers);
connect(ui->configurationList, SIGNAL(currentTextChanged(QString)),
this, SLOT(onConfigurationSelectionChanged(QString)));
mConfigurationModel = new QStandardItemModel(0, 2, this);
mConfigurationModel->setHorizontalHeaderItem(0, new QStandardItem(QString("Name")));
mConfigurationModel->setHorizontalHeaderItem(1, new QStandardItem(QString("Value")));
connect(mConfigurationModel, SIGNAL(itemChanged(QStandardItem*)),
this, SLOT(onConfigurationChanged(QStandardItem*)));
ui->configurationView->setModel(mConfigurationModel);
ui->configurationView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
ui->configurationView->verticalHeader()->hide();
ui->configurationView->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
ui->configurationView->setSelectionMode(QAbstractItemView::SingleSelection);
}
sh::MainWindow::~MainWindow()
{
delete ui;
}
void sh::MainWindow::closeEvent(QCloseEvent *event)
{
this->hide();
event->ignore();
}
void sh::MainWindow::onIdle()
{
if (mRequestShowWindow)
{
mRequestShowWindow = false;
show();
}
if (mRequestExit)
{
QApplication::exit();
return;
}
boost::mutex::scoped_lock lock(mSync->mUpdateMutex);
mIgnoreMaterialChange = true;
QString selected;
QModelIndex selectedIndex = ui->materialList->selectionModel()->currentIndex();
if (selectedIndex.isValid())
selected = mMaterialModel->data(selectedIndex, Qt::DisplayRole).toString();
QStringList list;
for (std::vector<std::string>::const_iterator it = mState.mMaterialList.begin(); it != mState.mMaterialList.end(); ++it)
{
list.push_back(QString::fromStdString(*it));
}
if (mMaterialModel->stringList() != list)
{
mMaterialModel->setStringList(list);
// quick hack to keep our selection when the model has changed
if (!selected.isEmpty())
for (int i=0; i<mMaterialModel->rowCount(); ++i)
{
const QModelIndex& index = mMaterialModel->index(i,0);
if (mMaterialModel->data(index, Qt::DisplayRole).toString() == selected)
{
ui->materialList->setCurrentIndex(index);
break;
}
}
}
mIgnoreMaterialChange = false;
mIgnoreGlobalSettingChange = true;
for (std::map<std::string, std::string>::const_iterator it = mState.mGlobalSettingsMap.begin();
it != mState.mGlobalSettingsMap.end(); ++it)
{
QList<QStandardItem *> list = mGlobalSettingsModel->findItems(QString::fromStdString(it->first));
if (!list.empty()) // item was already there
{
// if it changed, set the value column
if (mGlobalSettingsModel->data(mGlobalSettingsModel->index(list.front()->row(), 1)).toString()
!= QString::fromStdString(it->second))
{
mGlobalSettingsModel->setItem(list.front()->row(), 1, new QStandardItem(QString::fromStdString(it->second)));
}
}
else // item wasn't there; insert new row
{
QList<QStandardItem*> toAdd;
QStandardItem* name = new QStandardItem(QString::fromStdString(it->first));
name->setFlags(name->flags() &= ~Qt::ItemIsEditable);
QStandardItem* value = new QStandardItem(QString::fromStdString(it->second));
toAdd.push_back(name);
toAdd.push_back(value);
mGlobalSettingsModel->appendRow(toAdd);
}
}
mIgnoreGlobalSettingChange = false;
mIgnoreConfigurationChange = true;
QList<QListWidgetItem*> selected_ = ui->configurationList->selectedItems();
QString selectedStr;
if (selected_.size())
selectedStr = selected_.front()->text();
ui->configurationList->clear();
for (std::vector<std::string>::const_iterator it = mState.mConfigurationList.begin(); it != mState.mConfigurationList.end(); ++it)
ui->configurationList->addItem(QString::fromStdString(*it));
if (!selectedStr.isEmpty())
for (int i=0; i<ui->configurationList->count(); ++i)
{
if (ui->configurationList->item(i)->text() == selectedStr)
{
ui->configurationList->setCurrentItem(ui->configurationList->item(i), QItemSelectionModel::ClearAndSelect);
}
}
mIgnoreConfigurationChange = false;
if (!mState.mErrors.empty())
{
ui->errorLog->append(QString::fromStdString(mState.mErrors));
mState.mErrors = "";
QColor color = ui->tabWidget->palette().color(QPalette::Normal, QPalette::Link);
ui->tabWidget->tabBar()->setTabTextColor(3, color);
}
// process query results
boost::mutex::scoped_lock lock2(mSync->mQueryMutex);
for (std::vector<Query*>::iterator it = mQueries.begin(); it != mQueries.end();)
{
if ((*it)->mDone)
{
if (typeid(**it) == typeid(ConfigurationQuery))
buildConfigurationModel(static_cast<ConfigurationQuery*>(*it));
else if (typeid(**it) == typeid(MaterialQuery))
buildMaterialModel(static_cast<MaterialQuery*>(*it));
else if (typeid(**it) == typeid(MaterialPropertyQuery))
{
MaterialPropertyQuery* q = static_cast<MaterialPropertyQuery*>(*it);
mIgnoreMaterialPropertyChange = true;
if (getSelectedMaterial().toStdString() == q->mName)
{
for (int i=0; i<mMaterialPropertyModel->rowCount(); ++i)
{
if (mMaterialPropertyModel->item(i,0)->text() == QString::fromStdString(q->mPropertyName))
{
mMaterialPropertyModel->item(i,1)->setText(QString::fromStdString(q->mValue));
if (mMaterialPropertyModel->item(i,1)->isCheckable())
mMaterialPropertyModel->item(i,1)->setCheckState ((q->mValue == "true")
? Qt::Checked : Qt::Unchecked);
}
}
}
mIgnoreMaterialPropertyChange = false;
}
delete *it;
it = mQueries.erase(it);
}
else
++it;
}
}
void sh::MainWindow::onMaterialSelectionChanged (const QModelIndex & current, const QModelIndex & previous)
{
if (mIgnoreMaterialChange)
return;
QString name = getSelectedMaterial();
if (!name.isEmpty())
requestQuery(new sh::MaterialQuery(name.toStdString()));
}
QString sh::MainWindow::getSelectedMaterial()
{
QModelIndex selectedIndex = ui->materialList->selectionModel()->currentIndex();
if (!selectedIndex.isValid())
return QString("");
return mMaterialProxyModel->data(selectedIndex, Qt::DisplayRole).toString();
}
void sh::MainWindow::onConfigurationSelectionChanged (const QString& current)
{
if (mIgnoreConfigurationChange)
return;
requestQuery(new sh::ConfigurationQuery(current.toStdString()));
}
void sh::MainWindow::onGlobalSettingChanged(QStandardItem *item)
{
if (mIgnoreGlobalSettingChange)
return; // we are only interested in changes by the user, not by the backend.
std::string name = mGlobalSettingsModel->data(mGlobalSettingsModel->index(item->row(), 0)).toString().toStdString();
std::string value = mGlobalSettingsModel->data(mGlobalSettingsModel->index(item->row(), 1)).toString().toStdString();
queueAction(new sh::ActionChangeGlobalSetting(name, value));
}
void sh::MainWindow::onConfigurationChanged (QStandardItem* item)
{
QList<QListWidgetItem*> items = ui->configurationList->selectedItems();
if (items.size())
{
std::string name = items.front()->text().toStdString();
std::string key = mConfigurationModel->data(mConfigurationModel->index(item->row(), 0)).toString().toStdString();
std::string value = mConfigurationModel->data(mConfigurationModel->index(item->row(), 1)).toString().toStdString();
queueAction(new sh::ActionChangeConfiguration(name, key, value));
requestQuery(new sh::ConfigurationQuery(name));
}
}
void sh::MainWindow::on_lineEdit_textEdited(const QString &arg1)
{
mMaterialProxyModel->setFilterFixedString(arg1);
}
void sh::MainWindow::on_actionSave_triggered()
{
queueAction (new sh::ActionSaveAll());
}
void sh::MainWindow::on_actionNewMaterial_triggered()
{
}
void sh::MainWindow::on_actionDeleteMaterial_triggered()
{
QModelIndex selectedIndex = ui->materialList->selectionModel()->currentIndex();
QString name = mMaterialProxyModel->data(selectedIndex, Qt::DisplayRole).toString();
queueAction (new sh::ActionDeleteMaterial(name.toStdString()));
}
void sh::MainWindow::queueAction(Action* action)
{
boost::mutex::scoped_lock lock(mSync->mActionMutex);
mActionQueue.push(action);
}
void sh::MainWindow::requestQuery(Query *query)
{
boost::mutex::scoped_lock lock(mSync->mActionMutex);
mQueries.push_back(query);
}
void sh::MainWindow::on_actionQuit_triggered()
{
hide();
}
void sh::MainWindow::on_actionNewConfiguration_triggered()
{
QInputDialog dialog(this);
QString text = QInputDialog::getText(this, tr("New Configuration"),
tr("Configuration name:"));
if (!text.isEmpty())
{
queueAction(new ActionCreateConfiguration(text.toStdString()));
}
}
void sh::MainWindow::on_actionDeleteConfiguration_triggered()
{
QList<QListWidgetItem*> items = ui->configurationList->selectedItems();
if (items.size())
queueAction(new ActionDeleteConfiguration(items.front()->text().toStdString()));
}
void sh::MainWindow::on_actionDeleteConfigurationProperty_triggered()
{
QList<QListWidgetItem*> items = ui->configurationList->selectedItems();
if (items.empty())
return;
std::string configurationName = items.front()->text().toStdString();
QModelIndex current = ui->configurationView->currentIndex();
if (!current.isValid())
return;
std::string propertyName = mConfigurationModel->data(mConfigurationModel->index(current.row(), 0)).toString().toStdString();
queueAction(new sh::ActionDeleteConfigurationProperty(configurationName, propertyName));
requestQuery(new sh::ConfigurationQuery(configurationName));
}
void sh::MainWindow::on_actionCloneMaterial_triggered()
{
QModelIndex selectedIndex = ui->materialList->selectionModel()->currentIndex();
QString name = mMaterialProxyModel->data(selectedIndex, Qt::DisplayRole).toString();
if (name.isEmpty())
return;
QInputDialog dialog(this);
QString text = QInputDialog::getText(this, tr("Clone material"),
tr("Name:"));
if (!text.isEmpty())
{
queueAction(new ActionCloneMaterial(name.toStdString(), text.toStdString()));
}
}
void sh::MainWindow::onContextMenuRequested(const QPoint &point)
{
QPoint globalPos = ui->materialView->viewport()->mapToGlobal(point);
QMenu menu;
QList <QAction*> actions;
actions.push_back(ui->actionNewProperty);
actions.push_back(ui->actionDeleteProperty);
actions.push_back(ui->actionCreatePass);
actions.push_back(ui->actionCreateTextureUnit);
menu.addActions(actions);
menu.exec(globalPos);
}
void sh::MainWindow::getContext(QModelIndex index, int* passIndex, int* textureIndex, bool* isInPass, bool* isInTextureUnit)
{
if (passIndex)
{
*passIndex = 0;
if (isInPass)
*isInPass = false;
QModelIndex passModelIndex = index;
// go up until we find the pass item.
while (getPropertyKey(passModelIndex) != "pass" && passModelIndex.isValid())
passModelIndex = passModelIndex.parent();
if (passModelIndex.isValid())
{
if (passModelIndex.column() != 0)
passModelIndex = passModelIndex.parent().child(passModelIndex.row(), 0);
for (int i=0; i<mMaterialPropertyModel->rowCount(); ++i)
{
if (mMaterialPropertyModel->data(mMaterialPropertyModel->index(i, 0)).toString() == QString("pass"))
{
if (mMaterialPropertyModel->index(i, 0) == passModelIndex)
{
if (isInPass)
*isInPass = true;
break;
}
++(*passIndex);
}
}
}
}
if (textureIndex)
{
*textureIndex = 0;
if (isInTextureUnit)
*isInTextureUnit = false;
QModelIndex texModelIndex = index;
// go up until we find the texture_unit item.
while (getPropertyKey(texModelIndex) != "texture_unit" && texModelIndex.isValid())
texModelIndex = texModelIndex.parent();
if (texModelIndex.isValid())
{
if (texModelIndex.column() != 0)
texModelIndex = texModelIndex.parent().child(texModelIndex.row(), 0);
for (int i=0; i<mMaterialPropertyModel->rowCount(texModelIndex.parent()); ++i)
{
if (texModelIndex.parent().child(i, 0).data().toString() == QString("texture_unit"))
{
if (texModelIndex.parent().child(i, 0) == texModelIndex)
{
if (isInTextureUnit)
*isInTextureUnit = true;
break;
}
++(*textureIndex);
}
}
}
}
}
std::string sh::MainWindow::getPropertyKey(QModelIndex index)
{
if (!index.parent().isValid())
return mMaterialPropertyModel->data(mMaterialPropertyModel->index(index.row(), 0)).toString().toStdString();
else
return index.parent().child(index.row(), 0).data().toString().toStdString();
}
std::string sh::MainWindow::getPropertyValue(QModelIndex index)
{
if (!index.parent().isValid())
return mMaterialPropertyModel->data(mMaterialPropertyModel->index(index.row(), 1)).toString().toStdString();
else
return index.parent().child(index.row(), 1).data().toString().toStdString();
}
void sh::MainWindow::onMaterialPropertyChanged(QStandardItem *item)
{
if (mIgnoreMaterialPropertyChange)
return;
QString material = getSelectedMaterial();
if (material.isEmpty())
return;
// handle checkboxes being checked/unchecked
std::string value = getPropertyValue(item->index());
if (item->data(Qt::UserRole).toInt() == MaterialProperty::Boolean)
{
if (item->checkState() == Qt::Checked && value != "true")
value = "true";
else if (item->checkState() == Qt::Unchecked && value == "true")
value = "false";
item->setText(QString::fromStdString(value));
}
// handle inherited properties being changed, i.e. overridden by the current (derived) material
if (item->data(Qt::UserRole+1).toInt() == MaterialProperty::Inherited_Unchanged)
{
QColor normalColor = ui->materialView->palette().color(QPalette::Normal, QPalette::WindowText);
mIgnoreMaterialPropertyChange = true;
mMaterialPropertyModel->item(item->index().row(), 0)
->setData(QVariant(MaterialProperty::Inherited_Changed), Qt::UserRole+1);
mMaterialPropertyModel->item(item->index().row(), 0)
->setData(normalColor, Qt::ForegroundRole);
mMaterialPropertyModel->item(item->index().row(), 1)
->setData(QVariant(MaterialProperty::Inherited_Changed), Qt::UserRole+1);
mMaterialPropertyModel->item(item->index().row(), 1)
->setData(normalColor, Qt::ForegroundRole);
mIgnoreMaterialPropertyChange = false;
ui->materialView->scrollTo(mMaterialSortModel->mapFromSource(item->index()));
}
if (!item->index().parent().isValid())
{
// top level material property
queueAction(new ActionSetMaterialProperty(
material.toStdString(), getPropertyKey(item->index()), value));
}
else if (getPropertyKey(item->index()) == "texture_unit")
{
// texture unit name changed
int passIndex, textureIndex;
getContext(item->index(), &passIndex, &textureIndex);
std::cout << "passIndex " << passIndex << " " << textureIndex << std::endl;
queueAction(new ActionChangeTextureUnitName(
material.toStdString(), passIndex, textureIndex, value));
}
else if (item->index().parent().data().toString() == "pass")
{
// pass property
int passIndex;
getContext(item->index(), &passIndex, NULL);
/// \todo if shaders are changed, check that the material provides all properties needed by the shader
queueAction(new ActionSetPassProperty(
material.toStdString(), passIndex, getPropertyKey(item->index()), value));
}
else if (item->index().parent().data().toString() == "shader_properties")
{
// shader property
int passIndex;
getContext(item->index(), &passIndex, NULL);
queueAction(new ActionSetShaderProperty(
material.toStdString(), passIndex, getPropertyKey(item->index()), value));
}
else if (item->index().parent().data().toString() == "texture_unit")
{
// texture property
int passIndex, textureIndex;
getContext(item->index(), &passIndex, &textureIndex);
queueAction(new ActionSetTextureProperty(
material.toStdString(), passIndex, textureIndex, getPropertyKey(item->index()), value));
}
}
void sh::MainWindow::buildMaterialModel(MaterialQuery *data)
{
mMaterialPropertyModel->clear();
mMaterialPropertyModel->setHorizontalHeaderItem(0, new QStandardItem(QString("Name")));
mMaterialPropertyModel->setHorizontalHeaderItem(1, new QStandardItem(QString("Value")));
for (std::map<std::string, MaterialProperty>::const_iterator it = data->mProperties.begin();
it != data->mProperties.end(); ++it)
{
addProperty(mMaterialPropertyModel->invisibleRootItem(), it->first, it->second);
}
for (std::vector<PassInfo>::iterator it = data->mPasses.begin();
it != data->mPasses.end(); ++it)
{
QStandardItem* passItem = new QStandardItem (QString("pass"));
passItem->setFlags(passItem->flags() &= ~Qt::ItemIsEditable);
passItem->setData(QVariant(static_cast<int>(MaterialProperty::Object)), Qt::UserRole);
if (it->mShaderProperties.size())
{
QStandardItem* shaderPropertiesItem = new QStandardItem (QString("shader_properties"));
shaderPropertiesItem->setFlags(shaderPropertiesItem->flags() &= ~Qt::ItemIsEditable);
shaderPropertiesItem->setData(QVariant(static_cast<int>(MaterialProperty::Object)), Qt::UserRole);
for (std::map<std::string, MaterialProperty>::iterator pit = it->mShaderProperties.begin();
pit != it->mShaderProperties.end(); ++pit)
{
addProperty(shaderPropertiesItem, pit->first, pit->second);
}
passItem->appendRow(shaderPropertiesItem);
}
for (std::map<std::string, MaterialProperty>::iterator pit = it->mProperties.begin();
pit != it->mProperties.end(); ++pit)
{
addProperty(passItem, pit->first, pit->second);
}
for (std::vector<TextureUnitInfo>::iterator tIt = it->mTextureUnits.begin();
tIt != it->mTextureUnits.end(); ++tIt)
{
QStandardItem* unitItem = new QStandardItem (QString("texture_unit"));
unitItem->setFlags(unitItem->flags() &= ~Qt::ItemIsEditable);
unitItem->setData(QVariant(static_cast<int>(MaterialProperty::Object)), Qt::UserRole);
QStandardItem* nameItem = new QStandardItem (QString::fromStdString(tIt->mName));
nameItem->setData(QVariant(static_cast<int>(MaterialProperty::Object)), Qt::UserRole);
QList<QStandardItem*> texUnit;
texUnit << unitItem << nameItem;
for (std::map<std::string, MaterialProperty>::iterator pit = tIt->mProperties.begin();
pit != tIt->mProperties.end(); ++pit)
{
addProperty(unitItem, pit->first, pit->second);
}
passItem->appendRow(texUnit);
}
QList<QStandardItem*> toAdd;
toAdd << passItem;
toAdd << new QStandardItem(QString(""));
mMaterialPropertyModel->appendRow(toAdd);
}
ui->materialView->expandAll();
ui->materialView->resizeColumnToContents(0);
ui->materialView->resizeColumnToContents(1);
}
void sh::MainWindow::addProperty(QStandardItem *parent, const std::string &key, MaterialProperty value, bool scrollTo)
{
QList<QStandardItem*> toAdd;
QStandardItem* keyItem = new QStandardItem(QString::fromStdString(key));
keyItem->setFlags(keyItem->flags() &= ~Qt::ItemIsEditable);
keyItem->setData(QVariant(value.mType), Qt::UserRole);
keyItem->setData(QVariant(value.mSource), Qt::UserRole+1);
toAdd.push_back(keyItem);
QStandardItem* valueItem = NULL;
if (value.mSource != MaterialProperty::None)
{
valueItem = new QStandardItem(QString::fromStdString(value.mValue));
valueItem->setData(QVariant(value.mType), Qt::UserRole);
valueItem->setData(QVariant(value.mSource), Qt::UserRole+1);
toAdd.push_back(valueItem);
}
if (value.mSource == MaterialProperty::Inherited_Unchanged)
{
QColor color = ui->configurationView->palette().color(QPalette::Disabled, QPalette::WindowText);
keyItem->setData(color, Qt::ForegroundRole);
if (valueItem)
valueItem->setData(color, Qt::ForegroundRole);
}
if (value.mType == MaterialProperty::Boolean && valueItem)
{
valueItem->setCheckable(true);
valueItem->setCheckState((value.mValue == "true") ? Qt::Checked : Qt::Unchecked);
}
parent->appendRow(toAdd);
if (scrollTo)
ui->materialView->scrollTo(mMaterialSortModel->mapFromSource(keyItem->index()));
}
void sh::MainWindow::buildConfigurationModel(ConfigurationQuery *data)
{
while (mConfigurationModel->rowCount())
mConfigurationModel->removeRow(0);
for (std::map<std::string, std::string>::iterator it = data->mProperties.begin();
it != data->mProperties.end(); ++it)
{
QList<QStandardItem*> toAdd;
QStandardItem* name = new QStandardItem(QString::fromStdString(it->first));
name->setFlags(name->flags() &= ~Qt::ItemIsEditable);
QStandardItem* value = new QStandardItem(QString::fromStdString(it->second));
toAdd.push_back(name);
toAdd.push_back(value);
mConfigurationModel->appendRow(toAdd);
}
// add items that are in global settings, but not in this configuration (with a "inactive" color)
for (std::map<std::string, std::string>::const_iterator it = mState.mGlobalSettingsMap.begin();
it != mState.mGlobalSettingsMap.end(); ++it)
{
if (data->mProperties.find(it->first) == data->mProperties.end())
{
QColor color = ui->configurationView->palette().color(QPalette::Disabled, QPalette::WindowText);
QList<QStandardItem*> toAdd;
QStandardItem* name = new QStandardItem(QString::fromStdString(it->first));
name->setFlags(name->flags() &= ~Qt::ItemIsEditable);
name->setData(color, Qt::ForegroundRole);
QStandardItem* value = new QStandardItem(QString::fromStdString(it->second));
value->setData(color, Qt::ForegroundRole);
toAdd.push_back(name);
toAdd.push_back(value);
mConfigurationModel->appendRow(toAdd);
}
}
}
void sh::MainWindow::on_actionCreatePass_triggered()
{
QString material = getSelectedMaterial();
if (!material.isEmpty())
{
addProperty(mMaterialPropertyModel->invisibleRootItem(),
"pass", MaterialProperty("", MaterialProperty::Object, MaterialProperty::None), true);
queueAction (new ActionCreatePass(material.toStdString()));
}
}
void sh::MainWindow::on_actionDeleteProperty_triggered()
{
QModelIndex selectedIndex = mMaterialSortModel->mapToSource(ui->materialView->selectionModel()->currentIndex());
QString material = getSelectedMaterial();
if (material.isEmpty())
return;
mIgnoreMaterialPropertyChange = true;
if (getPropertyKey(selectedIndex) == "pass")
{
// delete whole pass
int passIndex;
getContext(selectedIndex, &passIndex, NULL);
if (passIndex == 0)
{
QMessageBox msgBox;
msgBox.setText("The first pass can not be deleted.");
msgBox.exec();
}
else
{
queueAction(new ActionDeletePass(material.toStdString(), passIndex));
mMaterialPropertyModel->removeRow(selectedIndex.row(), selectedIndex.parent());
}
}
else if (getPropertyKey(selectedIndex) == "texture_unit")
{
// delete whole texture unit
int passIndex, textureIndex;
getContext(selectedIndex, &passIndex, &textureIndex);
queueAction(new ActionDeleteTextureUnit(material.toStdString(), passIndex, textureIndex));
mMaterialPropertyModel->removeRow(selectedIndex.row(), selectedIndex.parent());
}
else if (!selectedIndex.parent().isValid())
{
// top level material property
MaterialProperty::Source source = static_cast<MaterialProperty::Source>(
mMaterialPropertyModel->itemFromIndex(selectedIndex)->data(Qt::UserRole+1).toInt());
if (source == MaterialProperty::Inherited_Unchanged)
{
QMessageBox msgBox;
msgBox.setText("Inherited properties can not be deleted.");
msgBox.exec();
}
else
{
queueAction(new ActionDeleteMaterialProperty(
material.toStdString(), getPropertyKey(selectedIndex)));
std::cout << "source is " << source << std::endl;
if (source == MaterialProperty::Inherited_Changed)
{
QColor inactiveColor = ui->materialView->palette().color(QPalette::Disabled, QPalette::WindowText);
mMaterialPropertyModel->item(selectedIndex.row(), 0)
->setData(QVariant(MaterialProperty::Inherited_Unchanged), Qt::UserRole+1);
mMaterialPropertyModel->item(selectedIndex.row(), 0)
->setData(inactiveColor, Qt::ForegroundRole);
mMaterialPropertyModel->item(selectedIndex.row(), 1)
->setData(QVariant(MaterialProperty::Inherited_Unchanged), Qt::UserRole+1);
mMaterialPropertyModel->item(selectedIndex.row(), 1)
->setData(inactiveColor, Qt::ForegroundRole);
// make sure to update the property's value
requestQuery(new sh::MaterialPropertyQuery(material.toStdString(), getPropertyKey(selectedIndex)));
}
else
mMaterialPropertyModel->removeRow(selectedIndex.row());
}
}
else if (selectedIndex.parent().data().toString() == "pass")
{
// pass property
int passIndex;
getContext(selectedIndex, &passIndex, NULL);
queueAction(new ActionDeletePassProperty(
material.toStdString(), passIndex, getPropertyKey(selectedIndex)));
mMaterialPropertyModel->removeRow(selectedIndex.row(), selectedIndex.parent());
}
else if (selectedIndex.parent().data().toString() == "shader_properties")
{
// shader property
int passIndex;
getContext(selectedIndex, &passIndex, NULL);
queueAction(new ActionDeleteShaderProperty(
material.toStdString(), passIndex, getPropertyKey(selectedIndex)));
mMaterialPropertyModel->removeRow(selectedIndex.row(), selectedIndex.parent());
}
else if (selectedIndex.parent().data().toString() == "texture_unit")
{
// texture property
int passIndex, textureIndex;
getContext(selectedIndex, &passIndex, &textureIndex);
queueAction(new ActionDeleteTextureProperty(
material.toStdString(), passIndex, textureIndex, getPropertyKey(selectedIndex)));
mMaterialPropertyModel->removeRow(selectedIndex.row(), selectedIndex.parent());
}
mIgnoreMaterialPropertyChange = false;
}
void sh::MainWindow::on_actionNewProperty_triggered()
{
QModelIndex selectedIndex = mMaterialSortModel->mapToSource(ui->materialView->selectionModel()->currentIndex());
QString material = getSelectedMaterial();
if (material.isEmpty())
return;
AddPropertyDialog* dialog = new AddPropertyDialog(this);
dialog->exec();
QString propertyName = dialog->mName;
QString defaultValue = "";
/// \todo check if this property name exists already
if (!propertyName.isEmpty())
{
int passIndex, textureIndex;
bool isInPass, isInTextureUnit;
getContext(selectedIndex, &passIndex, &textureIndex, &isInPass, &isInTextureUnit);
QList<QStandardItem*> items;
QStandardItem* keyItem = new QStandardItem(propertyName);
keyItem->setFlags(keyItem->flags() &= ~Qt::ItemIsEditable);
items << keyItem;
items << new QStandardItem(defaultValue);
// figure out which item the new property should be a child of
QModelIndex parentIndex = selectedIndex;
if (selectedIndex.data(Qt::UserRole) != MaterialProperty::Object)
parentIndex = selectedIndex.parent();
QStandardItem* parentItem;
if (!parentIndex.isValid())
parentItem = mMaterialPropertyModel->invisibleRootItem();
else
parentItem = mMaterialPropertyModel->itemFromIndex(parentIndex);
if (isInTextureUnit)
{
queueAction(new ActionSetTextureProperty(
material.toStdString(), passIndex, textureIndex, propertyName.toStdString(), defaultValue.toStdString()));
}
else if (isInPass)
{
if (selectedIndex.parent().child(selectedIndex.row(),0).data().toString() == "shader_properties"
|| selectedIndex.parent().data().toString() == "shader_properties")
{
queueAction(new ActionSetShaderProperty(
material.toStdString(), passIndex, propertyName.toStdString(), defaultValue.toStdString()));
}
else
{
queueAction(new ActionSetPassProperty(
material.toStdString(), passIndex, propertyName.toStdString(), defaultValue.toStdString()));
}
}
else
{
queueAction(new ActionSetMaterialProperty(
material.toStdString(), propertyName.toStdString(), defaultValue.toStdString()));
}
addProperty(parentItem, propertyName.toStdString(),
MaterialProperty (defaultValue.toStdString(), MaterialProperty::Misc, MaterialProperty::Normal), true);
/// \todo scroll to newly added property
}
}
void sh::MainWindow::on_actionCreateTextureUnit_triggered()
{
QString material = getSelectedMaterial();
if (material.isEmpty())
return;
QInputDialog dialog(this);
QString text = QInputDialog::getText(this, tr("New texture unit"),
tr("Texture unit name (for referencing in shaders):"));
if (!text.isEmpty())
{
QModelIndex selectedIndex = mMaterialSortModel->mapToSource(ui->materialView->selectionModel()->currentIndex());
int passIndex;
getContext(selectedIndex, &passIndex, NULL);
queueAction(new ActionCreateTextureUnit(material.toStdString(), passIndex, text.toStdString()));
// add to model
int index = 0;
for (int i=0; i<mMaterialPropertyModel->rowCount(); ++i)
{
if (mMaterialPropertyModel->data(mMaterialPropertyModel->index(i, 0)).toString() == QString("pass"))
{
if (index == passIndex)
{
addProperty(mMaterialPropertyModel->itemFromIndex(mMaterialPropertyModel->index(i, 0)),
"texture_unit", MaterialProperty(text.toStdString(), MaterialProperty::Object), true);
break;
}
++index;
}
}
}
}
void sh::MainWindow::on_clearButton_clicked()
{
ui->errorLog->clear();
}
void sh::MainWindow::on_tabWidget_currentChanged(int index)
{
QColor color = ui->tabWidget->palette().color(QPalette::Normal, QPalette::WindowText);
if (index == 3)
ui->tabWidget->tabBar()->setTabTextColor(3, color);
}

@ -0,0 +1,139 @@
#ifndef SHINY_EDITOR_MAINWINDOW_HPP
#define SHINY_EDITOR_MAINWINDOW_HPP
#include <QMainWindow>
#include <QSortFilterProxyModel>
#include <QStandardItemModel>
#include <QStringListModel>
#include <queue>
#include "Actions.hpp"
#include "Query.hpp"
#include "PropertySortModel.hpp"
namespace Ui {
class MainWindow;
}
namespace sh
{
struct SynchronizationState;
/**
* @brief A snapshot of the material system's state. Lock the mUpdateMutex before accessing.
*/
struct MaterialSystemState
{
std::vector<std::string> mMaterialList;
std::map<std::string, std::string> mGlobalSettingsMap;
std::vector<std::string> mConfigurationList;
std::vector<std::string> mMaterialFiles;
std::vector<std::string> mConfigurationFiles;
std::vector<std::string> mShaderSets;
std::string mErrors;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
// really should be an std::atomic
volatile bool mRequestShowWindow;
// dito
volatile bool mRequestExit;
SynchronizationState* mSync;
/// \todo Is there a better way to ignore manual model changes?
bool mIgnoreGlobalSettingChange;
bool mIgnoreConfigurationChange;
bool mIgnoreMaterialChange;
bool mIgnoreMaterialPropertyChange;
std::queue<Action*> mActionQueue;
std::vector<Query*> mQueries;
MaterialSystemState mState;
private:
Ui::MainWindow *ui;
// material tab
QStringListModel* mMaterialModel;
QSortFilterProxyModel* mMaterialProxyModel;
QStandardItemModel* mMaterialPropertyModel;
PropertySortModel* mMaterialSortModel;
// global settings tab
QStandardItemModel* mGlobalSettingsModel;
// configuration tab
QStandardItemModel* mConfigurationModel;
void queueAction(Action* action);
void requestQuery(Query* query);
void buildMaterialModel (MaterialQuery* data);
void buildConfigurationModel (ConfigurationQuery* data);
QString getSelectedMaterial();
/// get the context of an index in the material property model
void getContext(QModelIndex index, int* passIndex, int* textureIndex, bool* isInPass=NULL, bool* isInTextureUnit=NULL);
std::string getPropertyKey(QModelIndex index);
std::string getPropertyValue(QModelIndex index);
void addProperty (QStandardItem* parent, const std::string& key, MaterialProperty value, bool scrollTo=false);
protected:
void closeEvent(QCloseEvent *event);
public slots:
void onIdle();
void onMaterialSelectionChanged (const QModelIndex & current, const QModelIndex & previous);
void onConfigurationSelectionChanged (const QString& current);
void onGlobalSettingChanged (QStandardItem* item);
void onConfigurationChanged (QStandardItem* item);
void onMaterialPropertyChanged (QStandardItem* item);
void onContextMenuRequested(const QPoint& point);
private slots:
void on_lineEdit_textEdited(const QString &arg1);
void on_actionSave_triggered();
void on_actionNewMaterial_triggered();
void on_actionDeleteMaterial_triggered();
void on_actionQuit_triggered();
void on_actionNewConfiguration_triggered();
void on_actionDeleteConfiguration_triggered();
void on_actionDeleteConfigurationProperty_triggered();
void on_actionCloneMaterial_triggered();
void on_actionCreatePass_triggered();
void on_actionDeleteProperty_triggered();
void on_actionNewProperty_triggered();
void on_actionCreateTextureUnit_triggered();
void on_clearButton_clicked();
void on_tabWidget_currentChanged(int index);
};
}
#endif // MAINWINDOW_HPP

@ -0,0 +1,14 @@
#include "NewMaterialDialog.hpp"
#include "ui_newmaterialdialog.h"
NewMaterialDialog::NewMaterialDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::NewMaterialDialog)
{
ui->setupUi(this);
}
NewMaterialDialog::~NewMaterialDialog()
{
delete ui;
}

@ -0,0 +1,22 @@
#ifndef NEWMATERIALDIALOG_HPP
#define NEWMATERIALDIALOG_HPP
#include <QDialog>
namespace Ui {
class NewMaterialDialog;
}
class NewMaterialDialog : public QDialog
{
Q_OBJECT
public:
explicit NewMaterialDialog(QWidget *parent = 0);
~NewMaterialDialog();
private:
Ui::NewMaterialDialog *ui;
};
#endif // NEWMATERIALDIALOG_HPP

@ -0,0 +1,35 @@
#include "PropertySortModel.hpp"
#include "Query.hpp"
#include <iostream>
sh::PropertySortModel::PropertySortModel(QObject *parent)
: QSortFilterProxyModel(parent)
{
}
bool sh::PropertySortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
if (left.data(Qt::UserRole+1).toInt() != 0 && right.data(Qt::UserRole+1).toInt() != 0)
{
int sourceL = left.data(Qt::UserRole+1).toInt();
int sourceR = right.data(Qt::UserRole+1).toInt();
if (sourceL > sourceR)
return true;
else if (sourceR > sourceL)
return false;
}
int typeL = left.data(Qt::UserRole).toInt();
int typeR = right.data(Qt::UserRole).toInt();
if (typeL > typeR)
return true;
else if (typeR > typeL)
return false;
QString nameL = left.data().toString();
QString nameR = right.data().toString();
return nameL > nameR;
}

@ -0,0 +1,21 @@
#ifndef SHINY_EDITOR_PROPERTYSORTMODEL_H
#define SHINY_EDITOR_PROPERTYSORTMODEL_H
#include <QSortFilterProxyModel>
namespace sh
{
class PropertySortModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
PropertySortModel(QObject* parent);
protected:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
};
}
#endif

@ -0,0 +1,134 @@
#include "Query.hpp"
#include "../Main/Factory.hpp"
namespace sh
{
void Query::execute()
{
executeImpl();
mDone = true;
}
ConfigurationQuery::ConfigurationQuery(const std::string &name)
: mName(name)
{
}
void ConfigurationQuery::executeImpl()
{
sh::Factory::getInstance().listConfigurationSettings(mName, mProperties);
}
void MaterialQuery::executeImpl()
{
sh::MaterialInstance* instance = sh::Factory::getInstance().getMaterialInstance(mName);
if (instance->getParent())
mParent = static_cast<sh::MaterialInstance*>(instance->getParent())->getName();
// add the inherited properties
sh::PropertySetGet* parent = instance;
std::vector<std::string> inheritedPropertiesVector;
while (parent->getParent())
{
parent = parent->getParent();
const sh::PropertyMap& parentProperties = parent->listProperties();
for (PropertyMap::const_iterator it = parentProperties.begin(); it != parentProperties.end(); ++it)
{
MaterialProperty::Source source = MaterialProperty::Inherited_Unchanged;
MaterialProperty::Type type = getType(it->first, parent->getProperty(it->first));
mProperties[it->first] = MaterialProperty (
retrieveValue<sh::StringValue>(parent->getProperty(it->first), NULL).get(),
type, source);
inheritedPropertiesVector.push_back(it->first);
}
}
// add our properties
const sh::PropertyMap& ourProperties = instance->listProperties();
for (PropertyMap::const_iterator it = ourProperties.begin(); it != ourProperties.end(); ++it)
{
MaterialProperty::Source source =
(std::find(inheritedPropertiesVector.begin(), inheritedPropertiesVector.end(), it->first)
!= inheritedPropertiesVector.end()) ?
MaterialProperty::Inherited_Changed : MaterialProperty::Normal;
MaterialProperty::Type type = getType(it->first, instance->getProperty(it->first));
mProperties[it->first] = MaterialProperty (
retrieveValue<sh::StringValue>(instance->getProperty(it->first), NULL).get(),
type, source);
}
std::vector<MaterialInstancePass>* passes = instance->getPasses();
for (std::vector<MaterialInstancePass>::iterator it = passes->begin(); it != passes->end(); ++it)
{
mPasses.push_back(PassInfo());
const sh::PropertyMap& passProperties = it->listProperties();
for (PropertyMap::const_iterator pit = passProperties.begin(); pit != passProperties.end(); ++pit)
{
PropertyValuePtr property = it->getProperty(pit->first);
MaterialProperty::Type type = getType(pit->first, property);
if (typeid(*property).name() == typeid(sh::LinkedValue).name())
mPasses.back().mProperties[pit->first] = MaterialProperty("$" + property->_getStringValue(), type);
else
mPasses.back().mProperties[pit->first] = MaterialProperty(
retrieveValue<sh::StringValue>(property, NULL).get(), type);
}
const sh::PropertyMap& shaderProperties = it->mShaderProperties.listProperties();
for (PropertyMap::const_iterator pit = shaderProperties.begin(); pit != shaderProperties.end(); ++pit)
{
PropertyValuePtr property = it->mShaderProperties.getProperty(pit->first);
MaterialProperty::Type type = getType(pit->first, property);
if (typeid(*property).name() == typeid(sh::LinkedValue).name())
mPasses.back().mShaderProperties[pit->first] = MaterialProperty("$" + property->_getStringValue(), type);
else
mPasses.back().mShaderProperties[pit->first] = MaterialProperty(
retrieveValue<sh::StringValue>(property, NULL).get(), type);
}
std::vector<MaterialInstanceTextureUnit>* texUnits = &it->mTexUnits;
for (std::vector<MaterialInstanceTextureUnit>::iterator tIt = texUnits->begin(); tIt != texUnits->end(); ++tIt)
{
mPasses.back().mTextureUnits.push_back(TextureUnitInfo());
mPasses.back().mTextureUnits.back().mName = tIt->getName();
const sh::PropertyMap& unitProperties = tIt->listProperties();
for (PropertyMap::const_iterator pit = unitProperties.begin(); pit != unitProperties.end(); ++pit)
{
PropertyValuePtr property = tIt->getProperty(pit->first);
MaterialProperty::Type type = getType(pit->first, property);
if (typeid(*property).name() == typeid(sh::LinkedValue).name())
mPasses.back().mTextureUnits.back().mProperties[pit->first] = MaterialProperty(
"$" + property->_getStringValue(), MaterialProperty::Linked);
else
mPasses.back().mTextureUnits.back().mProperties[pit->first] = MaterialProperty(
retrieveValue<sh::StringValue>(property, NULL).get(), type);
}
}
}
}
MaterialProperty::Type MaterialQuery::getType(const std::string &key, PropertyValuePtr value)
{
if (typeid(*value).name() == typeid(sh::LinkedValue).name())
return MaterialProperty::Linked;
if (key == "vertex_program" || key == "fragment_program")
return MaterialProperty::Shader;
std::string valueStr = retrieveValue<sh::StringValue>(value, NULL).get();
if (valueStr == "false" || valueStr == "true")
return MaterialProperty::Boolean;
}
void MaterialPropertyQuery::executeImpl()
{
sh::MaterialInstance* m = sh::Factory::getInstance().getMaterialInstance(mName);
mValue = retrieveValue<sh::StringValue>(m->getProperty(mPropertyName), m).get();
}
}

@ -0,0 +1,121 @@
#ifndef SH_QUERY_H
#define SH_QUERY_H
#include <string>
#include <map>
#include <vector>
#include "../Main/PropertyBase.hpp"
namespace sh
{
class Query
{
public:
Query()
: mDone(false) {}
virtual ~Query();
void execute();
bool mDone;
protected:
virtual void executeImpl() = 0;
};
class ConfigurationQuery : public Query
{
public:
ConfigurationQuery(const std::string& name);
std::map<std::string, std::string> mProperties;
protected:
std::string mName;
virtual void executeImpl();
};
struct MaterialProperty
{
enum Type
{
Texture,
Color,
Boolean,
Shader,
Misc,
Linked,
Object // child object, i.e. pass, texture unit, shader properties
};
enum Source
{
Normal,
Inherited_Changed,
Inherited_Unchanged,
None // there is no property source (e.g. a pass, which does not have a name)
};
MaterialProperty() {}
MaterialProperty (const std::string& value, Type type, Source source=Normal)
: mValue(value), mType(type), mSource(source) {}
std::string mValue;
Type mType;
Source mSource;
};
struct TextureUnitInfo
{
std::string mName;
std::map<std::string, MaterialProperty> mProperties;
};
struct PassInfo
{
std::map<std::string, MaterialProperty> mShaderProperties;
std::map<std::string, MaterialProperty> mProperties;
std::vector<TextureUnitInfo> mTextureUnits;
};
class MaterialQuery : public Query
{
public:
MaterialQuery(const std::string& name)
: mName(name) {}
std::string mParent;
std::vector<PassInfo> mPasses;
std::map<std::string, MaterialProperty> mProperties;
protected:
std::string mName;
virtual void executeImpl();
MaterialProperty::Type getType (const std::string& key, PropertyValuePtr value);
};
class MaterialPropertyQuery : public Query
{
public:
MaterialPropertyQuery(const std::string& name, const std::string& propertyName)
: mName(name), mPropertyName(propertyName)
{
}
std::string mValue;
std::string mName;
std::string mPropertyName;
protected:
virtual void executeImpl();
};
}
#endif

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddPropertyDialog</class>
<widget class="QDialog" name="AddPropertyDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>257</width>
<height>133</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Property name</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Editing widget</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBox">
<item>
<property name="text">
<string>Checkbox</string>
</property>
</item>
<item>
<property name="text">
<string>Shader</string>
</property>
</item>
<item>
<property name="text">
<string>Color</string>
</property>
</item>
<item>
<property name="text">
<string>Texture</string>
</property>
</item>
<item>
<property name="text">
<string>Other</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>AddPropertyDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>AddPropertyDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

@ -0,0 +1,420 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>647</width>
<height>512</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="verticalLayout">
<item>
<widget class="sh::ColoredTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<property name="accessibleName">
<string/>
</property>
<attribute name="title">
<string>Materials</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLineEdit" name="lineEdit">
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string>Search</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="materialList">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QToolBar" name="toolBar1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<addaction name="actionNewMaterial"/>
<addaction name="actionCloneMaterial"/>
<addaction name="actionDeleteMaterial"/>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="verticalLayoutWidget2">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QTreeView" name="materialView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QToolBar" name="toolBar4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonIconOnly</enum>
</property>
<addaction name="actionNewProperty"/>
<addaction name="actionDeleteProperty"/>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab2">
<attribute name="title">
<string>Global settings</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QTableView" name="globalSettingsView"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Configurations</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QListWidget" name="configurationList"/>
</item>
<item>
<widget class="QToolBar" name="toolBar2">
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<addaction name="actionNewConfiguration"/>
<addaction name="actionDeleteConfiguration"/>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget2">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QTableView" name="configurationView"/>
</item>
<item>
<widget class="QToolBar" name="toolBar2_2">
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<addaction name="actionDeleteConfigurationProperty"/>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Errors</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QTextEdit" name="errorLog">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clearButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Clear</string>
</property>
<property name="icon">
<iconset theme="edit-clear"/>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox"/>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>647</width>
<height>25</height>
</rect>
</property>
<property name="defaultUp">
<bool>false</bool>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionSave"/>
<addaction name="actionQuit"/>
</widget>
<widget class="QMenu" name="menuMaterial">
<property name="title">
<string>Material</string>
</property>
<addaction name="actionNewMaterial"/>
<addaction name="actionCloneMaterial"/>
<addaction name="actionDeleteMaterial"/>
<addaction name="actionChange_parent"/>
</widget>
<widget class="QMenu" name="menuHistory">
<property name="title">
<string>History</string>
</property>
</widget>
<addaction name="menuFile"/>
<addaction name="menuMaterial"/>
<addaction name="menuHistory"/>
</widget>
<action name="actionQuit">
<property name="icon">
<iconset theme="application-exit">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>Quit</string>
</property>
</action>
<action name="actionSave">
<property name="icon">
<iconset theme="document-save">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>Save</string>
</property>
<property name="toolTip">
<string>Save all</string>
</property>
</action>
<action name="actionDeleteMaterial">
<property name="icon">
<iconset theme="edit-delete">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>Delete</string>
</property>
<property name="toolTip">
<string>Delete selected material</string>
</property>
</action>
<action name="actionChange_parent">
<property name="text">
<string>Change parent...</string>
</property>
</action>
<action name="actionNewMaterial">
<property name="icon">
<iconset theme="document-new">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>New</string>
</property>
<property name="toolTip">
<string>Create a new material</string>
</property>
</action>
<action name="actionCloneMaterial">
<property name="icon">
<iconset theme="edit-copy">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>Clone</string>
</property>
<property name="toolTip">
<string>Clone selected material</string>
</property>
</action>
<action name="actionDeleteConfiguration">
<property name="icon">
<iconset theme="edit-delete">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>Delete</string>
</property>
<property name="toolTip">
<string>Delete selected configuration</string>
</property>
<property name="shortcut">
<string>Del</string>
</property>
</action>
<action name="actionNewConfiguration">
<property name="icon">
<iconset theme="document-new">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>New</string>
</property>
<property name="toolTip">
<string>Create a new configuration</string>
</property>
</action>
<action name="actionDeleteConfigurationProperty">
<property name="icon">
<iconset theme="edit-delete">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>Delete</string>
</property>
<property name="toolTip">
<string>Delete property</string>
</property>
</action>
<action name="actionDeleteProperty">
<property name="icon">
<iconset theme="remove">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>Delete</string>
</property>
<property name="toolTip">
<string>Delete item</string>
</property>
</action>
<action name="actionNewProperty">
<property name="icon">
<iconset theme="add">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>New property</string>
</property>
</action>
<action name="actionCreatePass">
<property name="icon">
<iconset theme="edit-add">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>Create pass</string>
</property>
</action>
<action name="actionCreateTextureUnit">
<property name="icon">
<iconset theme="edit-add">
<normaloff/>
</iconset>
</property>
<property name="text">
<string>Create texture unit</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>sh::ColoredTabWidget</class>
<extends>QTabWidget</extends>
<header>ColoredTabWidget.hpp</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewMaterialDialog</class>
<widget class="QDialog" name="NewMaterialDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>385</width>
<height>198</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Parent material</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEdit_2"/>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>File</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBox"/>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>NewMaterialDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>NewMaterialDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
Loading…
Cancel
Save