@@ -398,9 +399,9 @@ void MainWindow::onNetworkFinished(QNetworkReply *reply) {
if (reply->error() == QNetworkReply::NoError) {
try {
QSettings settings("mitsuba-renderer.org", "qtgui");
- ProgramVersion remote(QString(reply->readAll()));
- ProgramVersion ignoredVersion(settings.value("ignoredVersion", "0.0.0").toString());
- ProgramVersion local(MTS_VERSION);
+ Version remote(QString(reply->readAll()).toStdString());
+ Version ignoredVersion(settings.value("ignoredVersion", "0.0.0").toString().toStdString());
+ Version local(MTS_VERSION);
if (local < remote) {
if (!m_manualUpdateCheck && remote == ignoredVersion)
@@ -413,7 +414,7 @@ void MainWindow::onNetworkFinished(QNetworkReply *reply) {
QMessageBox::information(this, tr("Installed version is current"),
QString("You're up to date!
"
"Mitsuba %1 is still the newest version available.
")
- .arg(local.toString()), QMessageBox::Ok);
+ .arg(local.toString().c_str()), QMessageBox::Ok);
}
} catch (const std::exception &e) {
/* Got something weird and couldn't parse the version string --
@@ -618,14 +619,16 @@ SceneContext *MainWindow::loadScene(const QString &qFileName) {
newResolver->addPath(filePath);
for (int i=0; iaddPath(m_searchPaths[i].toStdString());
-
- ref loadingThread
- = new SceneLoader(newResolver, filename.file_string());
LoadDialog *loaddlg = new LoadDialog(this);
+ SceneContext *result = NULL;
+ ref loadingThread;
loaddlg->setAttribute(Qt::WA_DeleteOnClose);
loaddlg->setWindowModality(Qt::ApplicationModal);
loaddlg->setWindowTitle("Loading ..");
loaddlg->show();
+
+retry:
+ loadingThread = new SceneLoader(newResolver, filename.file_string());
loadingThread->start();
while (loadingThread->isRunning()) {
@@ -633,14 +636,55 @@ SceneContext *MainWindow::loadScene(const QString &qFileName) {
loadingThread->wait(20);
}
loadingThread->join();
- loaddlg->close();
- SceneContext *result = loadingThread->getResult();
+ result = loadingThread->getResult();
if (result == NULL) {
- QMessageBox::critical(this, tr("Unable to load %1").arg(qFileName),
- QString(loadingThread->getError().c_str()),
- QMessageBox::Ok);
+ if (loadingThread->isVersionError()) {
+ Version version = loadingThread->getVersion();
+ int ret;
+ if (version.isValid()) {
+ ret = QMessageBox::question(this, tr("Version mismatch -- update scene file?"),
+ QString("The requested scene file is from an older version of Mitsuba "
+ "(%1). To work with version %2, it will need to be updated. If you "
+ "continue, Mitsuba will attempt a fully automated upgrade (note that a "
+ "backup copy will be made).\n\nProceed?")
+ .arg(version.toString().c_str())
+ .arg(MTS_VERSION), QMessageBox::Yes | QMessageBox::Cancel);
+ } else {
+ QMessageBox box(QMessageBox::Question, tr("Version mismatch -- update scene file?"),
+ (loadingThread->getError() + "\n\nAlternatively, if this file is from version 0.2.1"
+ "(the last release without explicit version numbers), you can perform a fully "
+ "automated upgrade from this version. A backup copy will be made in this case.").c_str());
+ QPushButton *version021Button = box.addButton(tr("Assume version 0.2.1?"), QMessageBox::YesRole);
+ box.addButton(tr("Cancel"), QMessageBox::RejectRole);
+ ret = box.exec();
+ if (box.clickedButton() == version021Button) {
+ version = Version(0, 2, 1);
+ ret = QMessageBox::Yes;
+ }
+ }
+ if (ret == QMessageBox::Yes) {
+ loaddlg->expand();
+
+ UpgradeManager upgradeMgr(newResolver);
+ try {
+ upgradeMgr.performUpgrade(filename.file_string().c_str(), version);
+ goto retry;
+ } catch (const std::exception &ex) {
+ QMessageBox::critical(this, tr("Unable to update %1").arg(qFileName),
+ QString(ex.what()), QMessageBox::Ok);
+ }
+ } else {
+ QMessageBox::critical(this, tr("Unable to load %1").arg(qFileName),
+ QString("No upgrade was performed -- giving up."), QMessageBox::Ok);
+ }
+ } else {
+ QMessageBox::critical(this, tr("Unable to load %1").arg(qFileName),
+ QString(loadingThread->getError().c_str()),
+ QMessageBox::Ok);
+ }
}
+ loaddlg->close();
return result;
}
diff --git a/src/qtgui/save.cpp b/src/qtgui/save.cpp
index 2485b95e..09827fee 100644
--- a/src/qtgui/save.cpp
+++ b/src/qtgui/save.cpp
@@ -17,7 +17,6 @@
*/
#include "save.h"
-#include
static QDomElement findUniqueChild(QDomElement element, const char *tagName) {
QDomElement result;
@@ -101,26 +100,7 @@ static void setProperties(QDomDocument &doc, QDomElement &element,
}
void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
- QDomDocument doc("MitsubaScene");
- QFile file(ctx->fileName);
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QMessageBox::critical(parent, parent->tr("Unable to save"),
- parent->tr("Unable to save changes: could not open the original scene file %1. "
- "Was this file moved or deleted in the meantime?").arg(ctx->fileName),
- QMessageBox::Ok);
- return;
- }
- if (!doc.setContent(&file)) {
- QMessageBox::critical(parent, parent->tr("Unable to save"),
- parent->tr("Unable to save changes: could not parse the original scene file %1. "
- "Was this file modified in the meantime?").arg(ctx->fileName),
- QMessageBox::Ok);
- file.close();
- return;
- }
- file.close();
-
- QDomElement root = doc.documentElement();
+ QDomElement root = ctx->doc.documentElement();
// ====================================================================
// Serialize the camera configuration
@@ -128,7 +108,7 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
QDomElement camera = findUniqueChild(root, "camera");
if (camera.isNull()) {
- camera = doc.createElement("camera");
+ camera = ctx->doc.createElement("camera");
camera.setAttribute("type", "perspective");
root.insertAfter(camera, QDomNode());
}
@@ -136,7 +116,7 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
QDomElement fovProperty = findProperty(camera, "fov");
if (fovProperty.isNull()) {
- fovProperty = doc.createElement("float");
+ fovProperty = ctx->doc.createElement("float");
fovProperty.setAttribute("name", "fov");
camera.insertBefore(fovProperty, QDomNode());
}
@@ -144,7 +124,7 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
QDomElement focusDepthProperty = findProperty(camera, "focusDepth");
if (focusDepthProperty.isNull()) {
- focusDepthProperty = doc.createElement("float");
+ focusDepthProperty = ctx->doc.createElement("float");
focusDepthProperty.setAttribute("name", "focusDepth");
camera.insertBefore(focusDepthProperty, QDomNode());
}
@@ -152,13 +132,13 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
QDomElement cameraTransform = findUniqueChild(camera, "transform");
if (cameraTransform.isNull()) {
- cameraTransform = doc.createElement("transform");
+ cameraTransform = ctx->doc.createElement("transform");
cameraTransform.setAttribute("name", "toWorld");
camera.insertBefore(cameraTransform, QDomNode());
}
removeChildren(cameraTransform);
- QDomElement lookAt = doc.createElement("lookAt");
+ QDomElement lookAt = ctx->doc.createElement("lookAt");
cameraTransform.insertAfter(lookAt, QDomNode());
Vector direction = sceneCamera->getInverseViewTransform()(Vector(0,0,1)),
@@ -166,7 +146,7 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
Point t, p = sceneCamera->getInverseViewTransform()(Point(0,0,0));
if (sceneCamera->getViewTransform().det3x3() < 0) {
- QDomElement scale = doc.createElement("scale");
+ QDomElement scale = ctx->doc.createElement("scale");
scale.setAttribute("x", "-1");
cameraTransform.insertBefore(scale, lookAt);
}
@@ -182,15 +162,15 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
QDomElement newSampler, sampler = findUniqueChild(camera, "sampler");
if (sampler.isNull()) {
- newSampler = doc.createElement("sampler");
+ newSampler = ctx->doc.createElement("sampler");
camera.appendChild(newSampler);
} else {
- newSampler = doc.createElement("sampler");
+ newSampler = ctx->doc.createElement("sampler");
camera.insertAfter(newSampler, sampler);
camera.removeChild(sampler);
}
- setProperties(doc, newSampler, ctx->scene->getSampler()->getProperties());
+ setProperties(ctx->doc, newSampler, ctx->scene->getSampler()->getProperties());
// ====================================================================
// Serialize the film configuration
@@ -198,7 +178,7 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
QDomElement film = findUniqueChild(camera, "film");
if (film.isNull()) {
- film = doc.createElement("film");
+ film = ctx->doc.createElement("film");
film.setAttribute("type", "exrfilm");
camera.insertAfter(film, QDomNode());
}
@@ -207,13 +187,13 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
QDomElement heightProperty = findProperty(film, "height");
if (widthProperty.isNull()) {
- widthProperty = doc.createElement("integer");
+ widthProperty = ctx->doc.createElement("integer");
widthProperty.setAttribute("name", "width");
film.insertBefore(widthProperty, QDomNode());
}
if (heightProperty.isNull()) {
- heightProperty = doc.createElement("integer");
+ heightProperty = ctx->doc.createElement("integer");
heightProperty.setAttribute("name", "height");
film.insertBefore(heightProperty, QDomNode());
}
@@ -227,14 +207,14 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
QDomElement gamma = findProperty(film, "gamma");
if (method.isNull()) {
- method = doc.createElement("string");
+ method = ctx->doc.createElement("string");
method.setAttribute("name", "toneMappingMethod");
film.insertBefore(method, QDomNode());
}
method.setAttribute("value", ctx->toneMappingMethod == EReinhard ? "reinhard" : "gamma");
if (gamma.isNull()) {
- gamma = doc.createElement("float");
+ gamma = ctx->doc.createElement("float");
gamma.setAttribute("name", "gamma");
film.insertBefore(gamma, QDomNode());
}
@@ -242,7 +222,7 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
if (ctx->toneMappingMethod == EGamma) {
if (exposure.isNull()) {
- exposure = doc.createElement("float");
+ exposure = ctx->doc.createElement("float");
exposure.setAttribute("name", "exposure");
film.insertBefore(exposure, QDomNode());
}
@@ -253,12 +233,12 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
film.removeChild(reinhardBurn);
} else {
if (reinhardKey.isNull()) {
- reinhardKey = doc.createElement("float");
+ reinhardKey = ctx->doc.createElement("float");
reinhardKey.setAttribute("name", "reinhardKey");
film.insertBefore(reinhardKey, QDomNode());
}
if (reinhardBurn.isNull()) {
- reinhardBurn = doc.createElement("float");
+ reinhardBurn = ctx->doc.createElement("float");
reinhardBurn.setAttribute("name", "reinhardBurn");
film.insertBefore(reinhardBurn, QDomNode());
}
@@ -279,15 +259,15 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
QDomElement newRFilter, rfilter = findUniqueChild(film, "rfilter");
if (rfilter.isNull()) {
- newRFilter = doc.createElement("rfilter");
+ newRFilter = ctx->doc.createElement("rfilter");
film.appendChild(rfilter);
} else {
- newRFilter = doc.createElement("rfilter");
+ newRFilter = ctx->doc.createElement("rfilter");
film.insertAfter(newRFilter, rfilter);
film.removeChild(rfilter);
}
- setProperties(doc, newRFilter, ctx->scene->getCamera()->
+ setProperties(ctx->doc, newRFilter, ctx->scene->getCamera()->
getFilm()->getReconstructionFilter()->getProperties());
// ====================================================================
@@ -295,16 +275,16 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
// ====================================================================
QDomElement oldIntegratorNode = findUniqueChild(root, "integrator");
- QDomElement newIntegratorNode = doc.createElement("integrator");
+ QDomElement newIntegratorNode = ctx->doc.createElement("integrator");
const Integrator *integrator = ctx->scene->getIntegrator();
- setProperties(doc, newIntegratorNode, integrator->getProperties());
+ setProperties(ctx->doc, newIntegratorNode, integrator->getProperties());
QDomElement currentIntegratorNode = newIntegratorNode;
while (integrator->getSubIntegrator() != NULL) {
integrator = integrator->getSubIntegrator();
- QDomElement childIntegratorNode = doc.createElement("integrator");
- setProperties(doc, childIntegratorNode, integrator->getProperties());
+ QDomElement childIntegratorNode = ctx->doc.createElement("integrator");
+ setProperties(ctx->doc, childIntegratorNode, integrator->getProperties());
currentIntegratorNode.appendChild(childIntegratorNode);
currentIntegratorNode = childIntegratorNode;
}
@@ -312,6 +292,7 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
root.insertBefore(newIntegratorNode, oldIntegratorNode);
root.removeChild(oldIntegratorNode);
+ QFile file;
file.setFileName(targetFile);
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
QMessageBox::critical(parent, parent->tr("Unable to save"),
@@ -324,9 +305,14 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
is more suitable for human consumption ..
Beware: the code below is tailored to Qt's
output and won't work on arbitrary XML files */
- QString textContent = doc.toString();
+ QString textContent = ctx->doc.toString();
QTextStream input(&textContent);
QTextStream output(&file);
+ cleanupXML(input, output);
+ file.close();
+}
+
+void cleanupXML(QTextStream &input, QTextStream &output) {
QRegExp
filenameRegExp("filename=\"[^\"]*\""),
nameRegExp("name=\"[^\"]*\""),
@@ -362,10 +348,15 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
int nameMatch = nameRegExp.indexIn(line),
filenameMatch = filenameRegExp.indexIn(line),
nameLength = nameRegExp.matchedLength();
+
if (tagMatch != -1 && nameMatch != -1 && filenameMatch == -1) {
- line = line.left(tagLength) + line.mid(nameMatch, nameLength) + " "
- + line.mid(tagMatch+tagLength, nameMatch-(tagMatch+tagLength))
- + line.mid(nameMatch+nameLength);
+ QString a = line.mid(tagLength, nameMatch-tagLength).trimmed(),
+ b = line.mid(nameMatch+nameLength).trimmed();
+ line = line.left(tagLength) + line.mid(nameMatch, nameLength);
+ if (a.length() > 0)
+ line += " " + a;
+ if (b.length() > 0)
+ line += " " + b;
}
/* Add an extra newline if this is an object tag, and if there
@@ -414,6 +405,8 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
hasContents = true;
} else if (line.endsWith(" >")) {
line = line.left(line.size()-2) + QString(">");
+ } else if (line.endsWith("?>")) {
+ hasContents = true;
}
if (closeTag.indexIn(line) == 0)
@@ -421,6 +414,4 @@ void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile) {
output << line << endl;
}
- file.close();
}
-
diff --git a/src/qtgui/save.h b/src/qtgui/save.h
index 35e4043d..3be6eae2 100644
--- a/src/qtgui/save.h
+++ b/src/qtgui/save.h
@@ -19,3 +19,4 @@
#include "common.h"
extern void saveScene(QWidget *parent, SceneContext *ctx, const QString &targetFile);
+extern void cleanupXML(QTextStream &input, QTextStream &output);
diff --git a/src/qtgui/sceneloader.cpp b/src/qtgui/sceneloader.cpp
index bae198b0..610121c9 100644
--- a/src/qtgui/sceneloader.cpp
+++ b/src/qtgui/sceneloader.cpp
@@ -27,6 +27,7 @@
SceneLoader::SceneLoader(FileResolver *resolver, const std::string &filename)
: Thread("load"), m_resolver(resolver), m_filename(filename) {
m_wait = new WaitFlag();
+ m_versionError = false;
}
SceneLoader::~SceneLoader() {
@@ -35,9 +36,7 @@ SceneLoader::~SceneLoader() {
void SceneLoader::run() {
Thread::getThread()->setFileResolver(m_resolver);
SAXParser* parser = new SAXParser();
- std::string lowerCase = m_filename;
- for(size_t i=0; iparse(m_filename.c_str());
+
+ try {
+ parser->parse(m_filename.c_str());
+ } catch (const VersionException &ex) {
+ m_versionError = true;
+ m_version = ex.getVersion();
+ throw;
+ }
+
ref scene = handler->getScene();
scene->setSourceFile(m_filename);
@@ -105,10 +112,19 @@ void SceneLoader::run() {
SLog(EError, "Unable to load scene: no film found!");
if (scene->getLuminaires().size() == 0)
SLog(EError, "Unable to load scene: no light sources found!");
-
Vector2i size = scene->getFilm()->getSize();
Camera *camera = scene->getCamera();
+ /* Also generate a DOM representation for the Qt-based GUI */
+ QFile file(m_filename.c_str());
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ Log(EError, "Unable to open the file \"%s\"", m_filename.c_str());
+ QString errorMsg;
+ int line, column;
+ if (!m_result->doc.setContent(&file, &errorMsg, &line, &column))
+ SLog(EError, "Unable to parse file: error %s at line %i, colum %i",
+ errorMsg.toStdString().c_str(), line, column);
+
m_result->scene = scene;
m_result->sceneResID = Scheduler::getInstance()->registerResource(scene);
m_result->renderJob = NULL;
diff --git a/src/qtgui/sceneloader.h b/src/qtgui/sceneloader.h
index 498105e8..68af16a2 100644
--- a/src/qtgui/sceneloader.h
+++ b/src/qtgui/sceneloader.h
@@ -35,6 +35,8 @@ public:
inline SceneContext *getResult() { return m_result; }
inline const std::string &getError() const { return m_error; }
+ inline bool isVersionError() const { return m_versionError; }
+ inline const Version &getVersion() const { return m_version; }
protected:
virtual ~SceneLoader();
private:
@@ -42,6 +44,8 @@ private:
ref m_wait;
SceneContext *m_result;
std::string m_error, m_filename;
+ bool m_versionError;
+ Version m_version;
};
#endif // __SCENELOADER_H
diff --git a/src/qtgui/updatedlg.cpp b/src/qtgui/updatedlg.cpp
index 6e8df666..b0032329 100644
--- a/src/qtgui/updatedlg.cpp
+++ b/src/qtgui/updatedlg.cpp
@@ -19,19 +19,19 @@
#include "ui_updatedlg.h"
#include "updatedlg.h"
-UpdateDialog::UpdateDialog(QWidget *parent, const ProgramVersion &local,
- const ProgramVersion &remote) : QDialog(parent),
+UpdateDialog::UpdateDialog(QWidget *parent, const Version &local,
+ const Version &remote) : QDialog(parent),
ui(new Ui::UpdateDialog) {
ui->setupUi(this);
+ m_remoteVersion = remote.toString().c_str();
ui->versionLabel->setText(QApplication::translate("UpdateDialog",
"Version %1 has been released (you are using %2). Would you like to visit the download page?",
- 0, QApplication::UnicodeUTF8).arg(remote.toString()).arg(local.toString()));
+ 0, QApplication::UnicodeUTF8).arg(m_remoteVersion).arg(local.toString().c_str()));
ui->changeView->setHtml("Loading change log ..");
m_networkManager = new QNetworkAccessManager(this);
connect(m_networkManager, SIGNAL(finished(QNetworkReply *)),
this, SLOT(onNetworkFinished(QNetworkReply *)));
m_networkReply = m_networkManager->get(QNetworkRequest(QUrl("http://www.mitsuba-renderer.org/changelog.html")));
- m_remoteVersion = remote.toString();
}
void UpdateDialog::onNetworkFinished(QNetworkReply *reply) {
diff --git a/src/qtgui/updatedlg.h b/src/qtgui/updatedlg.h
index d1e7bc3b..57185c9e 100644
--- a/src/qtgui/updatedlg.h
+++ b/src/qtgui/updatedlg.h
@@ -29,8 +29,8 @@ namespace Ui {
class UpdateDialog : public QDialog {
Q_OBJECT
public:
- UpdateDialog(QWidget *parent, const ProgramVersion &local,
- const ProgramVersion &remote);
+ UpdateDialog(QWidget *parent, const Version &local,
+ const Version &remote);
~UpdateDialog();
protected slots:
void on_skipButton_clicked();
diff --git a/src/qtgui/upgrade.cpp b/src/qtgui/upgrade.cpp
new file mode 100644
index 00000000..15142ecd
--- /dev/null
+++ b/src/qtgui/upgrade.cpp
@@ -0,0 +1,166 @@
+/*
+ This file is part of Mitsuba, a physically based rendering system.
+
+ Copyright (c) 2007-2011 by Wenzel Jakob and others.
+
+ Mitsuba is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License Version 3
+ as published by the Free Software Foundation.
+
+ Mitsuba is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "upgrade.h"
+#include "save.h"
+#include
+#include
+#include
+
+struct VersionComparator {
+ inline bool operator()(const std::pair &s1,
+ const std::pair &s2) const {
+ return s1.first < s2.first;
+ }
+};
+
+class XSLTMessageHandler : public QAbstractMessageHandler {
+public:
+ XSLTMessageHandler() : m_fatalError(false) { }
+
+ void handleMessage(QtMsgType type, const QString &_descr, const QUrl &id, const QSourceLocation &loc) {
+ QString descr(_descr);
+ int paragraphStart = descr.indexOf("");
+ int paragraphEnd = descr.indexOf("
");
+ if (paragraphStart != -1 && paragraphEnd != -1)
+ descr = descr.mid(paragraphStart+3, paragraphEnd-paragraphStart-3);
+
+ if (loc.isNull())
+ SLog(EWarn, "%s", descr.toStdString().c_str());
+ else
+ SLog(EWarn, "%s (line %i, column %i, url=%s)", descr.toStdString().c_str(),
+ loc.line(), loc.column(), id.toString().toStdString().c_str());
+
+ if (type == QtFatalMsg)
+ m_fatalError = true;
+ }
+
+ inline bool fatalError() const { return m_fatalError; }
+private:
+ bool m_fatalError;
+};
+
+UpgradeManager::UpgradeManager(const FileResolver *resolver) : m_resolver(resolver){
+ fs::path transformationPath =
+ resolver->resolveAbsolute("data/schema/scene.xsd").parent_path();
+
+ fs::directory_iterator it(transformationPath), end;
+ SLog(EInfo, "Searching for transformations..");
+
+ for (; it != end; ++it) {
+ fs::path file = *it;
+ if (boost::to_lower_copy(file.extension()) != ".xsl" ||
+ !boost::starts_with(file.filename(), "upgrade_"))
+ continue;
+ std::string filename = file.filename();
+ Version version(filename.substr(8, filename.length()-12));
+ m_transformations.push_back(std::make_pair(version, file));
+ }
+
+ std::sort(m_transformations.begin(), m_transformations.end(), VersionComparator());
+
+ for (size_t i=0; i"
+ << endl << endl;
+ cleanupXML(input, output);
+ file.close();
+}
diff --git a/src/qtgui/upgrade.h b/src/qtgui/upgrade.h
new file mode 100644
index 00000000..aa1bd06c
--- /dev/null
+++ b/src/qtgui/upgrade.h
@@ -0,0 +1,35 @@
+/*
+ This file is part of Mitsuba, a physically based rendering system.
+
+ Copyright (c) 2007-2011 by Wenzel Jakob and others.
+
+ Mitsuba is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License Version 3
+ as published by the Free Software Foundation.
+
+ Mitsuba is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#if !defined(__UPGRADEMGR_H)
+#define __UPGRADEMGR_H
+
+#include "common.h"
+
+class UpgradeManager : public QObject {
+ Q_OBJECT
+public:
+ UpgradeManager(const FileResolver *resolver);
+
+ void performUpgrade(const QString &path, const Version &version);
+private:
+ const FileResolver *m_resolver;
+ std::vector > m_transformations;
+};
+
+#endif // __UPGRADEMGR_H
diff --git a/src/textures/scale.cpp b/src/textures/scale.cpp
index 885315fa..e95fd9eb 100644
--- a/src/textures/scale.cpp
+++ b/src/textures/scale.cpp
@@ -18,8 +18,7 @@
#include
#include
-#include
-#include
+#include
MTS_NAMESPACE_BEGIN
@@ -31,6 +30,10 @@ MTS_NAMESPACE_BEGIN
class ScalingTexture : public Texture {
public:
ScalingTexture(const Properties &props) : Texture(props) {
+ if (props.hasProperty("value"))
+ m_nested = new ConstantSpectrumTexture(
+ props.getSpectrum("value"));
+
if (props.hasProperty("scale") && props.getType("scale") == Properties::EFloat)
m_scale = Spectrum(props.getFloat("scale", 1.0f));
else
@@ -49,11 +52,10 @@ public:
}
void addChild(const std::string &name, ConfigurableObject *child) {
- if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) {
+ if (child->getClass()->derivesFrom(MTS_CLASS(Texture)))
m_nested = static_cast(child);
- } else {
+ else
Texture::addChild(name, child);
- }
}
Spectrum getValue(const Intersection &its) const {