mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 05:26:39 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			952 lines
		
	
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			952 lines
		
	
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "MainWindow.hpp"
 | 
						|
#include "ui_mainwindow.h"
 | 
						|
 | 
						|
#include <iostream>
 | 
						|
 | 
						|
#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);
 | 
						|
}
 |