diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2016-06-07 12:12:33 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2016-06-28 09:32:08 +0000 |
commit | 65885a1f1f3416a426fc78a8514839470d83bced (patch) | |
tree | d080f084d05582977a65e4842a863a814edf5f39 | |
parent | 531d8fe22a52b5d0e98096d71dd7d7a81368121c (diff) |
Creator plugin launches embedded editor
There's not yet any interaction between embedded editor
and creator, such as opening the correct file.
Change-Id: I1b8507ca209ba2387e0c1dfa8657bd45560a671a
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
57 files changed, 1678 insertions, 1003 deletions
diff --git a/creatorplugin/creatorplugin.pro b/creatorplugin/creatorplugin.pro index 41fd120..b9f3d15 100644 --- a/creatorplugin/creatorplugin.pro +++ b/creatorplugin/creatorplugin.pro @@ -1,17 +1,23 @@ DEFINES += QT3DSCENEEDITOR_LIBRARY -QT += qml quick +QT += qml quick quickwidgets DEPENDPATH += ../editorlib INCLUDEPATH += ../editorlib # Qt3DSceneEditor files -SOURCES += qt3dsceneeditorplugin.cpp +SOURCES += qt3dsceneeditorplugin.cpp \ + qt3dsceneeditorfactory.cpp \ + qt3dsceneeditorw.cpp \ + qt3dsceneeditordocument.cpp HEADERS += qt3dsceneeditorplugin.h \ + qt3dsceneeditorfactory.h \ + qt3dsceneeditorw.h \ qt3dsceneeditor_global.h \ - qt3dsceneeditorconstants.h + qt3dsceneeditorconstants.h \ + qt3dsceneeditordocument.h RESOURCES += creatorplugin.qrc @@ -68,6 +74,7 @@ LIBS += -L$$EDITORLIBDIR -lqt3dsceneeditor # Install necessary files under creator editordll.path = $$IDE_BIN_PATH editordll.files = $$EDITORLIBDIR/$$EDITORLIBNAME +editordll.CONFIG = no_check_exist wizardfiles.path = $$IDE_DATA_PATH/templates/wizards/files/qt3dsceneeditor wizardfiles.files = \ diff --git a/creatorplugin/qt3dsceneeditor_global.h b/creatorplugin/qt3dsceneeditor_global.h index f233c3e..22a8e1b 100644 --- a/creatorplugin/qt3dsceneeditor_global.h +++ b/creatorplugin/qt3dsceneeditor_global.h @@ -1,3 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D Editor of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #pragma once #include <QtGlobal> diff --git a/creatorplugin/qt3dsceneeditorconstants.h b/creatorplugin/qt3dsceneeditorconstants.h index 7567024..c4ef899 100644 --- a/creatorplugin/qt3dsceneeditorconstants.h +++ b/creatorplugin/qt3dsceneeditorconstants.h @@ -1,3 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D Editor of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #pragma once namespace Qt3DSceneEditor { @@ -6,5 +34,13 @@ namespace Constants { const char ACTION_ID[] = "Qt3DSceneEditor.Action"; const char MENU_ID[] = "Qt3DSceneEditor.Menu"; +const char C_QT3DSCENEEDITOR[] = "Qt5.Qt3DSceneEditor"; +const char QT3DSCENEEDITOR_ID[] = "Qt5.Qt3DSceneEditor"; +const char C_QT3DSCENEEDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors", "Qt3D Scene Editor"); + +const char C_QT3DSCENEEDITOR_MIMETYPE[] = "application/qt3dsceneeditor"; + +const char C_OPEN_EDITOR[] = "Qt3DSceneEditor.OpenEditor"; + } // namespace Qt3DSceneEditor } // namespace Constants diff --git a/creatorplugin/qt3dsceneeditordocument.cpp b/creatorplugin/qt3dsceneeditordocument.cpp new file mode 100644 index 0000000..febea51 --- /dev/null +++ b/creatorplugin/qt3dsceneeditordocument.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D Editor of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qt3dsceneeditordocument.h" +#include "qt3dsceneeditorplugin.h" +#include "qt3dsceneeditorconstants.h" + +#include <coreplugin/icore.h> +#include <coreplugin/editormanager/editormanager.h> + +using namespace Utils; + +namespace Qt3DSceneEditor { +namespace Internal { + +enum { debugQt3DSceneEditorDocument = 0 }; + +Qt3DSceneEditorDocument::Qt3DSceneEditorDocument(QObject *parent) : + IDocument(parent) +{ + setId(Qt3DSceneEditor::Constants::QT3DSCENEEDITOR_ID); + setMimeType(QLatin1String(Qt3DSceneEditor::Constants::C_QT3DSCENEEDITOR_MIMETYPE)); + + if (debugQt3DSceneEditorDocument) + qDebug() << __FUNCTION__; +} + +Core::IDocument::OpenResult Qt3DSceneEditorDocument::open(QString *errorString, + const QString &fileName, + const QString &realFileName) +{ + Q_UNUSED(errorString) + + if (debugQt3DSceneEditorDocument) + qDebug() << __FUNCTION__ << fileName << realFileName; + + setBlockDirtyChanged(true); + + // TODO: How to pass the actual file to open to launched editor? + + setFilePath(FileName::fromString(fileName)); + setBlockDirtyChanged(false); + m_shouldAutoSave = false; + + emit loaded(true); + return OpenResult::Success; +} + +bool Qt3DSceneEditorDocument::save(QString *errorString, const QString &name, bool autoSave) +{ + Q_UNUSED(errorString) + + if (debugQt3DSceneEditorDocument) + qDebug() << __FUNCTION__ << name << autoSave; + + const FileName oldFileName = filePath(); + const FileName actualName = name.isEmpty() ? oldFileName : FileName::fromString(name); + if (actualName.isEmpty()) + return false; + + m_blockDirtyChanged = true; + + // TODO: How to pass the save command to editor + + m_shouldAutoSave = false; + if (autoSave) { + m_blockDirtyChanged = false; + return true; + } + + setFilePath(actualName); + m_blockDirtyChanged = false; + + emit changed(); + return true; +} + +QByteArray Qt3DSceneEditorDocument::contents() const +{ + // TODO: is this function actually needed? + if (debugQt3DSceneEditorDocument) + qDebug() << __FUNCTION__; + return QByteArray(); +} + +bool Qt3DSceneEditorDocument::setContents(const QByteArray &contents) +{ + Q_UNUSED(contents) + // TODO: Do we need this? + if (debugQt3DSceneEditorDocument) + qDebug() << __FUNCTION__; + return true; +} + +void Qt3DSceneEditorDocument::setFilePath(const FileName &newName) +{ + if (debugQt3DSceneEditorDocument) + qDebug() << __FUNCTION__; + IDocument::setFilePath(newName); +} + +void Qt3DSceneEditorDocument::setBlockDirtyChanged(bool value) +{ + m_blockDirtyChanged = value; +} + +void Qt3DSceneEditorDocument::setShouldAutoSave(bool save) +{ + m_shouldAutoSave = save; +} + +bool Qt3DSceneEditorDocument::shouldAutoSave() const +{ + return m_shouldAutoSave; +} + +bool Qt3DSceneEditorDocument::isModified() const +{ + if (debugQt3DSceneEditorDocument) + qDebug() << __FUNCTION__; + return false; +} + +bool Qt3DSceneEditorDocument::isSaveAsAllowed() const +{ + return true; +} + +bool Qt3DSceneEditorDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type) +{ + if (debugQt3DSceneEditorDocument) + qDebug() << __FUNCTION__; + if (flag == FlagIgnore) + return true; + if (type == TypePermissions) { + emit changed(); + } else { + emit aboutToReload(); + QString fn = filePath().toString(); + const bool success = (open(errorString, fn, fn) == OpenResult::Success); + emit reloadFinished(success); + return success; + } + return true; +} + +void Qt3DSceneEditorDocument::dirtyChanged(bool dirty) +{ + if (m_blockDirtyChanged) + return; // We emit changed() afterwards, unless it was an autosave + + if (debugQt3DSceneEditorDocument) + qDebug() << __FUNCTION__ << dirty; + emit changed(); +} + +} // namespace Internal +} // namespace Qt3DSceneEditor diff --git a/creatorplugin/qt3dsceneeditordocument.h b/creatorplugin/qt3dsceneeditordocument.h new file mode 100644 index 0000000..31c3833 --- /dev/null +++ b/creatorplugin/qt3dsceneeditordocument.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D Editor of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include <coreplugin/idocument.h> + + +namespace Qt3DSceneEditor { +namespace Internal { + +class Qt3DSceneEditorPlugin; +class Qt3DSceneEditorW; + +class Qt3DSceneEditorDocument + : public Core::IDocument +{ + Q_OBJECT +public: + Qt3DSceneEditorDocument(QObject *parent = 0); + ~Qt3DSceneEditorDocument() {} + + //IDocument + OpenResult open(QString *errorString, const QString &fileName, + const QString &realFileName) override; + bool save(QString *errorString, const QString &fileName, bool autoSave) override; + QByteArray contents() const override; + bool setContents(const QByteArray &contents) override; + bool shouldAutoSave() const override; + bool isModified() const override; + bool isSaveAsAllowed() const override; + bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; + void setFilePath(const Utils::FileName &newName) override; + void setBlockDirtyChanged(bool value); + void setShouldAutoSave(bool save); + +signals: + void loaded(bool success); + +private: + void dirtyChanged(bool); + + bool m_blockDirtyChanged = false; + bool m_shouldAutoSave = false; +}; + +} // namespace Internal +} // namespace Qt3DSceneEditor diff --git a/creatorplugin/qt3dsceneeditorfactory.cpp b/creatorplugin/qt3dsceneeditorfactory.cpp new file mode 100644 index 0000000..96f4bf2 --- /dev/null +++ b/creatorplugin/qt3dsceneeditorfactory.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D Editor of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qt3dsceneeditorfactory.h" +#include "qt3dsceneeditorw.h" +#include "qt3dsceneeditorplugin.h" +#include "qt3dsceneeditorconstants.h" + +#include <coreplugin/fileiconprovider.h> +#include <coreplugin/editormanager/editormanager.h> +#include <projectexplorer/projectexplorerconstants.h> + +using namespace Qt3DSceneEditor::Internal; +using namespace Qt3DSceneEditor::Constants; + +Qt3DSceneEditorFactory::Qt3DSceneEditorFactory(Qt3DSceneEditorPlugin *plugin) : + Core::IEditorFactory(plugin), + m_plugin(plugin) +{ + setId(QT3DSCENEEDITOR_ID); + setMimeTypes(QStringList(QLatin1String(C_QT3DSCENEEDITOR_MIMETYPE))); + setDisplayName(qApp->translate("OpenWith::Editors", C_QT3DSCENEEDITOR_DISPLAY_NAME)); + + // TODO: Do we need special icon for qt3d.qrc files? +// Core::FileIconProvider::registerIconOverlayForSuffix( +// ProjectExplorer::Constants::FILEOVERLAY_QRC, "qt3d.qrc"); +} + +Core::IEditor *Qt3DSceneEditorFactory::createEditor() +{ + Core::Context context(C_QT3DSCENEEDITOR); + return new Qt3DSceneEditorW(context, m_plugin); +} diff --git a/creatorplugin/qt3dsceneeditorfactory.h b/creatorplugin/qt3dsceneeditorfactory.h new file mode 100644 index 0000000..91d901e --- /dev/null +++ b/creatorplugin/qt3dsceneeditorfactory.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D Editor of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include <coreplugin/editormanager/ieditorfactory.h> +#include <coreplugin/icontext.h> + +#include <QStringList> + +namespace Qt3DSceneEditor { +namespace Internal { + +class Qt3DSceneEditorPlugin; + +class Qt3DSceneEditorFactory : public Core::IEditorFactory +{ + Q_OBJECT + +public: + explicit Qt3DSceneEditorFactory(Qt3DSceneEditorPlugin *plugin); + + Core::IEditor *createEditor(); + +private: + Qt3DSceneEditorPlugin *m_plugin; +}; + +} // namespace Internal +} // namespace Qt3DSceneEditor diff --git a/creatorplugin/qt3dsceneeditorplugin.cpp b/creatorplugin/qt3dsceneeditorplugin.cpp index 64a5533..de363c6 100644 --- a/creatorplugin/qt3dsceneeditorplugin.cpp +++ b/creatorplugin/qt3dsceneeditorplugin.cpp @@ -26,6 +26,7 @@ ** ****************************************************************************/ #include "qt3dsceneeditorplugin.h" +#include "qt3dsceneeditorfactory.h" #include "qt3dsceneeditorconstants.h" #include "../editorlib/src/qt3dsceneeditor.h" @@ -35,14 +36,10 @@ #include <coreplugin/actionmanager/command.h> #include <coreplugin/actionmanager/actioncontainer.h> #include <coreplugin/coreconstants.h> +#include <coreplugin/designmode.h> #include <utils/mimetypes/mimedatabase.h> -#include <QAction> -#include <QMessageBox> -#include <QMainWindow> -#include <QMenu> - namespace Qt3DSceneEditor { namespace Internal { @@ -73,15 +70,8 @@ bool Qt3DSceneEditorPlugin::initialize(const QStringList &arguments, QString *er Utils::MimeDatabase::addMimeTypes(QLatin1String(":/qt3deditorplugin/mimetypes.xml")); - QAction *action = new QAction(tr("Launch External Qt3D Scene Editor..."), this); - Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID, - Core::Context(Core::Constants::C_GLOBAL)); - connect(action, SIGNAL(triggered()), this, SLOT(triggerAction())); - - Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID); - menu->menu()->setTitle(tr("Qt3D Scene Editor")); - menu->addAction(cmd); - Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); + Qt3DSceneEditorFactory *editor = new Qt3DSceneEditorFactory(this); + addAutoReleasedObject(editor); return true; } @@ -91,6 +81,9 @@ void Qt3DSceneEditorPlugin::extensionsInitialized() // Retrieve objects from the plugin manager's object pool // In the extensionsInitialized function, a plugin can be sure that all // plugins that depend on it are completely initialized. + + // TODO: How to enable design mode properly, as this doesn't seem to work + //Core::DesignMode::instance()->setDesignModeIsRequired(); } ExtensionSystem::IPlugin::ShutdownFlag Qt3DSceneEditorPlugin::aboutToShutdown() @@ -98,17 +91,9 @@ ExtensionSystem::IPlugin::ShutdownFlag Qt3DSceneEditorPlugin::aboutToShutdown() // Save settings // Disconnect from signals that are not needed during shutdown // Hide UI (if you add UI that is not in the main window directly) - return SynchronousShutdown; -} -void Qt3DSceneEditorPlugin::triggerAction() -{ - // TODO: How to handle application lifecycle? Currently closing the window doesn't destroy scene - if (!m_qmlEngine) { - register3DSceneEditorQML(); - m_qmlEngine = new QQmlApplicationEngine(this); - } - m_qmlEngine->load(QUrl(QStringLiteral("qrc:/qt3deditorlib/main.qml"))); + // TODO: Trigger save? + return SynchronousShutdown; } } // namespace Internal diff --git a/creatorplugin/qt3dsceneeditorplugin.h b/creatorplugin/qt3dsceneeditorplugin.h index 6aaccc8..b7719fc 100644 --- a/creatorplugin/qt3dsceneeditorplugin.h +++ b/creatorplugin/qt3dsceneeditorplugin.h @@ -25,6 +25,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #pragma once #include "qt3dsceneeditor_global.h" @@ -48,9 +49,6 @@ public: void extensionsInitialized(); ShutdownFlag aboutToShutdown(); -private slots: - void triggerAction(); - private: QQmlApplicationEngine *m_qmlEngine; }; diff --git a/creatorplugin/qt3dsceneeditorw.cpp b/creatorplugin/qt3dsceneeditorw.cpp new file mode 100644 index 0000000..b059185 --- /dev/null +++ b/creatorplugin/qt3dsceneeditorw.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D Editor of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qt3dsceneeditorw.h" +#include "qt3dsceneeditorplugin.h" +#include "qt3dsceneeditordocument.h" +#include "qt3dsceneeditorconstants.h" +#include "../editorlib/src/qt3dsceneeditor.h" + +#include <QQuickWidget> + +using namespace Utils; + +namespace Qt3DSceneEditor { +namespace Internal { + +enum { debugQt3DSceneEditorW = 0 }; + +Qt3DSceneEditorW::Qt3DSceneEditorW(const Core::Context &context, + Qt3DSceneEditorPlugin *plugin, + QWidget *parent) + : m_document(new Qt3DSceneEditorDocument(this)), + m_plugin(plugin), + m_sceneEditor(nullptr) +{ + Qt3DSceneEditorLib::register3DSceneEditorQML(); + m_sceneEditor = new QQuickWidget(parent); + m_sceneEditor->setResizeMode(QQuickWidget::SizeRootObjectToView); + m_sceneEditor->setSource(QUrl(QStringLiteral("qrc:/qt3deditorlib/PluginMain.qml"))); + + setContext(context); + setWidget(m_sceneEditor); + + if (debugQt3DSceneEditorW) + qDebug() << __FUNCTION__; +} + +Qt3DSceneEditorW::~Qt3DSceneEditorW() +{ + if (m_sceneEditor) + m_sceneEditor->deleteLater(); +} + +QWidget *Qt3DSceneEditorW::toolBar() +{ + return nullptr; +} + +} // namespace Internal +} // namespace Qt3DSceneEditor diff --git a/creatorplugin/qt3dsceneeditorw.h b/creatorplugin/qt3dsceneeditorw.h new file mode 100644 index 0000000..40b682e --- /dev/null +++ b/creatorplugin/qt3dsceneeditorw.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D Editor of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include "qt3dsceneeditordocument.h" + +#include <coreplugin/idocument.h> +#include <coreplugin/editormanager/ieditor.h> + +QT_BEGIN_NAMESPACE +class QQuickWidget; +QT_END_NAMESPACE + +namespace Qt3DSceneEditor { +namespace Internal { + +class Qt3DSceneEditorPlugin; +class Qt3DSceneEditorDocument; + +class Qt3DSceneEditorW : public Core::IEditor +{ + Q_OBJECT + +public: + Qt3DSceneEditorW(const Core::Context &context, + Qt3DSceneEditorPlugin *plugin, + QWidget *parent = 0); + ~Qt3DSceneEditorW() override; + + // IEditor + Core::IDocument *document() override { return m_document; } + QWidget *toolBar() override; + +private: + Qt3DSceneEditorDocument *m_document; + Qt3DSceneEditorPlugin *m_plugin; + QQuickWidget *m_sceneEditor; +}; + +} // namespace Internal +} // namespace Qt3DSceneEditor diff --git a/editorlib/qml.qrc b/editorlib/qml.qrc index befd775..9d5dc89 100644 --- a/editorlib/qml.qrc +++ b/editorlib/qml.qrc @@ -4,7 +4,9 @@ <file>meshes/defaultmesh.obj</file> <file>meshes/spotlight.obj</file> <file>meshes/directionallight.obj</file> - <file alias="main.qml">qml/main.qml</file> + <file alias="EditorContent.qml">qml/EditorContent.qml</file> + <file alias="PluginMain.qml">qml/PluginMain.qml</file> + <file alias="StandaloneMain.qml">qml/StandaloneMain.qml</file> <file alias="CameraEntityDelegate.qml">qml/CameraEntityDelegate.qml</file> <file alias="ComponentDelegate.qml">qml/ComponentDelegate.qml</file> <file alias="ComponentMenu.qml">qml/ComponentMenu.qml</file> diff --git a/editorlib/qml/ButtonViewHeader.qml b/editorlib/qml/ButtonViewHeader.qml index 8ce21fd..0c11c34 100644 --- a/editorlib/qml/ButtonViewHeader.qml +++ b/editorlib/qml/ButtonViewHeader.qml @@ -48,7 +48,7 @@ Rectangle { height: minimumHeaderHeight width: parent.width - color: mainwindow.paneColor + color: editorContent.paneColor onViewVisibleChanged: { showViewTitle(viewVisible) @@ -93,7 +93,7 @@ Rectangle { source: "images/reset.png" } onClicked: { - editorScene.undoHandler.createResetTransformCommand(selectedEntityName) + editorScene.undoHandler.createResetTransformCommand(editorContent.selectedEntityName) } } @@ -123,7 +123,7 @@ Rectangle { MouseArea { anchors.fill: parent onClicked: { - selectedEntityName = editorScene.sceneModel.entityName(entityTree.view.selection.currentIndex) + editorContent.selectedEntityName = editorScene.sceneModel.entityName(entityTree.view.selection.currentIndex) visibleEntityButton.entityEnabled = !visibleEntityButton.entityEnabled visibleEntityButton.visibleImageClicked() } diff --git a/editorlib/qml/CameraEntityDelegate.qml b/editorlib/qml/CameraEntityDelegate.qml index 8185fb5..d08e758 100644 --- a/editorlib/qml/CameraEntityDelegate.qml +++ b/editorlib/qml/CameraEntityDelegate.qml @@ -36,14 +36,14 @@ ComponentDelegate { componentType: EditorSceneItemComponentsModel.CameraEntity title: qsTr("Camera") + editorScene.emptyString - viewTitleVisible: cameraViewVisible + viewTitleVisible: editorContent.cameraViewVisible onChangeViewVisibity: { - cameraViewVisible = viewVisibility + editorContent.cameraViewVisible = viewVisibility } Component.onCompleted: { - if (!cameraViewVisible) + if (!editorContent.cameraViewVisible) height = minimumComponentHeight } @@ -63,7 +63,7 @@ ComponentDelegate { var oldValue = componentData.projectionType; if (oldValue !== newValue) { editorScene.undoHandler.createChangePropertyCommand( - selectedEntityName, componentType, + editorContent.selectedEntityName, componentType, "projectionType", newValue, oldValue, true); } } @@ -79,10 +79,10 @@ ComponentDelegate { label: Text { width: groupBoxControl.availableWidth text: groupBoxControl.title - color: enabled ? mainwindow.textColor : mainwindow.disabledTextColor - font.family: mainwindow.labelFontFamily - font.weight: mainwindow.labelFontWeight - font.pixelSize: mainwindow.labelFontPixelSize + color: enabled ? editorContent.textColor : editorContent.disabledTextColor + font.family: editorContent.labelFontFamily + font.weight: editorContent.labelFontWeight + font.pixelSize: editorContent.labelFontPixelSize elide: Text.ElideRight horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter diff --git a/editorlib/qml/ComponentMenu.qml b/editorlib/qml/ComponentMenu.qml index fef7169..f43bd69 100644 --- a/editorlib/qml/ComponentMenu.qml +++ b/editorlib/qml/ComponentMenu.qml @@ -33,7 +33,7 @@ Menu { title: qsTr("Add Component") + editorScene.emptyString MenuItem { - text: selectedEntityName + text: editorContent.selectedEntityName enabled: false } @@ -48,7 +48,7 @@ Menu { entityTree.addNewEntity(EditorUtils.CameraEntity) // When a new camera is added, it is automatically selected editorScene.undoHandler.createCopyCameraPropertiesCommand( - selectedEntityName); + editorContent.selectedEntityName); editorScene.undoHandler.endMacro() } } @@ -69,7 +69,7 @@ Menu { iconSource: "images/picker.png" enabled: !editorScene.multiSelection onTriggered: { - componentPropertiesView.model.appendNewComponent(sceneModel.ObjectPicker) + componentPropertiesView.model.appendNewComponent(EditorSceneItemComponentsModel.ObjectPicker) } } @@ -95,7 +95,7 @@ Menu { } else { // Doublecheck that we don't try to remove the scene root if (entityTreeView.selection.currentIndex !== editorScene.sceneModel.sceneEntityIndex()) - editorScene.undoHandler.createRemoveEntityCommand(selectedEntityName) + editorScene.undoHandler.createRemoveEntityCommand(editorContent.selectedEntityName) } } } @@ -113,8 +113,8 @@ Menu { editorScene.undoHandler.endMacro() editorScene.restoreMultiSelection(editorScene.multiSelectionList) } else { - var currentSelection = selectedEntity.entity() - editorScene.undoHandler.createDuplicateEntityCommand(selectedEntityName) + var currentSelection = editorContent.selectedEntity.entity() + editorScene.undoHandler.createDuplicateEntityCommand(editorContent.selectedEntityName) editorScene.restoreSelection(currentSelection) } } @@ -124,7 +124,7 @@ Menu { enabled: !editorScene.multiSelection && !entityTreeView.sceneRootSelected iconSource: "images/copy.png" onTriggered: { - mainwindow.copyEntity(selectedEntityName) + editorContent.copyEntity(editorContent.selectedEntityName) } } MenuItem { @@ -132,23 +132,23 @@ Menu { enabled: !editorScene.multiSelection && !entityTreeView.sceneRootSelected iconSource: "images/cut.png" onTriggered: { - mainwindow.cutEntity(selectedEntityName, selectedEntity) + editorContent.cutEntity(editorContent.selectedEntityName, editorContent.selectedEntity) } } MenuItem { text: qsTr("Paste (Ctrl + v)") + editorScene.emptyString - enabled: trackMousePosition && !editorScene.multiSelection + enabled: editorContent.trackMousePosition && !editorScene.multiSelection && (!entityTree.treeviewPasting || (entityTree.treeviewPasting && editorScene.sceneModel.canReparent( editorScene.sceneModel.editorSceneItemFromIndex( editorScene.sceneModel.getModelIndexByName( - selectedEntityName)), + editorContent.selectedEntityName)), editorScene.sceneModel.editorSceneItemFromIndex( editorScene.sceneModel.getModelIndexByName( editorScene.clipboardContent)), true))) iconSource: "images/paste.png" onTriggered: { - mainwindow.pasteEntity() + editorContent.pasteEntity() } } MenuItem { @@ -156,7 +156,7 @@ Menu { iconSource: "images/reset_all.png" enabled: !editorScene.multiSelection && !entityTreeView.sceneRootSelected onTriggered: { - editorScene.undoHandler.createResetEntityCommand(selectedEntityName) + editorScene.undoHandler.createResetEntityCommand(editorContent.selectedEntityName) } } MenuItem { @@ -165,7 +165,7 @@ Menu { enabled: !editorScene.multiSelection && !entityTreeView.sceneRootSelected && !entityTreeView.cameraSelected onTriggered: { - editorScene.undoHandler.createResetTransformCommand(selectedEntityName) + editorScene.undoHandler.createResetTransformCommand(editorContent.selectedEntityName) } } MenuItem { @@ -181,8 +181,8 @@ Menu { reparentList = editorScene.sceneModel.parentList(editorScene.multiSelectionList) groupCenter = editorScene.getMultiSelectionCenter() } else { - reparentList[0] = selectedEntityName - groupCenter = selectedEntity.selectionBoxCenter() + reparentList[0] = editorContent.selectedEntityName + groupCenter = editorContent.selectedEntity.selectionBoxCenter() } // TODO: Allow creating groups under other entities? diff --git a/editorlib/qml/DragHandle.qml b/editorlib/qml/DragHandle.qml index 6dde71d..e54bc1f 100644 --- a/editorlib/qml/DragHandle.qml +++ b/editorlib/qml/DragHandle.qml @@ -40,7 +40,7 @@ Item { id: handleRect anchors.fill: parent anchors.margins: 4 - color: mainwindow.selectionColor + color: editorContent.selectionColor } property int handleType: EditorScene.DragNone diff --git a/editorlib/qml/EditorContent.qml b/editorlib/qml/EditorContent.qml new file mode 100644 index 0000000..4ab123d --- /dev/null +++ b/editorlib/qml/EditorContent.qml @@ -0,0 +1,697 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D Editor of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.2 +import QtQuick.Dialogs 1.2 +import QtQml.Models 2.2 +import QtQml 2.2 +import Qt3D.Core 2.0 +import Qt.labs.settings 1.0 +import com.theqtcompany.SceneEditor3D 1.0 + +Item { + id: editorContent + anchors.fill: parent + + property var selectedEntity: null + property string selectedEntityName: "" + property url saveFileUrl: "" + property url defaultFolder: "file:///" + property url saveFolder: "file:///" + property url textureFolder: "file:///" + property url importFolder: "file:///" + property string saveFileTitleAddition: { + if (saveFileUrl != "") + " - " + saveFileUrl.toString().substring(saveFileUrl.toString().lastIndexOf("/") + 1) + else + saveFileUrl.toString() + } + + property int currentHelperPlane: 1 + property alias selectedEntityType: generalPropertyView.entityType + + property bool trackMousePosition: false + property int mousePosY: -1 + property int mousePosX: -1 + + property color textColor: "#ffffff" + property color disabledTextColor: "#a0a1a2" + property color selectionColor: "#43adee" + property color listHighlightColor: "#585a5c" + property color paneBackgroundColor: "#2e2f30" + property color paneColor: "#373839" + property color viewBorderColor: "#000000" + property color itemBackgroundColor: "#46484a" + property color itemColor: "#cccccc" + property color iconHighlightColor: "#26282a" + property string labelFontFamily: "Open Sans" + property int labelFontWeight: Font.Normal + property int labelFontPixelSize: 12 + property int maximumControlWidth: 200 + property int controlMargin: 4 + + property bool transformViewVisible: true + property bool materialViewVisible: true + property bool meshViewVisible: true + property bool lightViewVisible: true + property bool cameraViewVisible: true + + property real qlcControlHeight: 28 + + property string systemLanguage: editorScene.language + property alias editorScene: editorScene + + function checkUnsavedChanges() { + if (!editorScene.undoHandler.isClean()) { + closingDialog.open() + return false + } + return true + } + + function fileLoad() { + if (!editorScene.undoHandler.isClean()) { + saveUnsavedDialog.newFile = false + saveUnsavedDialog.open() + } else { + loadFileDialog.folder = saveFolder + loadFileDialog.open() + } + } + + function fileSave() { + if (saveFileUrl == "") { + saveFileDialog.folder = saveFolder + saveFileDialog.open() + // No previous autosave file, no need to delete anything + } else { + editorScene.saveScene(saveFileUrl) + editorScene.deleteScene(saveFileUrl, true) + } + } + + function fileSaveAs() { + if (editorContent.saveFileUrl != "") + editorScene.deleteScene(editorContent.saveFileUrl, true) + saveFileDialog.folder = saveFolder + saveFileDialog.open() + } + + function undo() { + editorScene.undoHandler.undo() + } + + function redo() { + editorScene.undoHandler.redo() + } + + function fileNew() { + if (!editorScene.undoHandler.isClean()) { + saveUnsavedDialog.newFile = true + saveUnsavedDialog.open() + } else { + editorScene.resetScene() + showNormalYPlane() + saveFileUrl = "" + } + } + + function showNormalXPlane() { + editorScene.helperPlane.enabled = true + editorScene.helperPlaneTransform.rotation = + editorScene.helperPlaneTransform.fromAxisAndAngle(0, 1, 0, 90) + currentHelperPlane = 0 + } + + function showNormalYPlane() { + editorScene.helperPlane.enabled = true + editorScene.helperPlaneTransform.rotation = + editorScene.helperPlaneTransform.fromAxisAndAngle(1, 0, 0, 90) + currentHelperPlane = 1 + } + + function showNormalZPlane() { + editorScene.helperPlane.enabled = true + editorScene.helperPlaneTransform.rotation = + editorScene.helperPlaneTransform.fromAxisAndAngle(0, 0, 1, 90) + currentHelperPlane = 2 + } + + function hideHelperPlane() { + editorScene.helperPlane.enabled = false + currentHelperPlane = 3 + } + + function copyEntity(entityName) { + if (entityName !== editorScene.sceneRootName()) { + // Disable possible previous cut operation + if (editorScene.clipboardOperation === EditorScene.ClipboardCut) { + var index = editorScene.sceneModel.getModelIndexByName( + editorScene.clipboardContent) + var sceneItem = editorScene.sceneModel.editorSceneItemFromIndex(index) + sceneItem.entity().enabled = true + } + trackMousePosition = true + editorScene.clipboardContent = entityName + editorScene.clipboardOperation = EditorScene.ClipboardCopy + // TODO: When to stop reading mouse movements when copy-pasting? + // TODO: When any other operation is done? + } + } + + function cutEntity(entityName, entity) { + if (entityName !== editorScene.sceneRootName()) { + trackMousePosition = true + editorScene.clipboardContent = entityName + editorScene.clipboardOperation = EditorScene.ClipboardCut + entity.entity().enabled = false + } + } + + function pasteEntity() { + if (editorScene.clipboardContent.length) { + var parentName = "" + if (entityTree.treeviewPasting) { + parentName = selectedEntityName + // Prevent pasting an entity under itself in tree + if (!editorScene.sceneModel.canReparent( + editorScene.sceneModel.editorSceneItemFromIndex( + editorScene.sceneModel.getModelIndexByName( + selectedEntityName)), + editorScene.sceneModel.editorSceneItemFromIndex( + editorScene.sceneModel.getModelIndexByName( + editorScene.clipboardContent)), true)) { + return + } + } + // When pasting to tree, world position is not used, and parent entity name is passed + editorScene.undoHandler.createPasteEntityCommand(editorScene.getWorldPosition( + mousePosX, mousePosY), parentName) + if (editorScene.clipboardOperation === EditorScene.ClipboardCut) { + trackMousePosition = false + editorScene.clipboardOperation = EditorScene.ClipboardNone + } + } + } + + Settings { + // Save view panel sizes + // Use detailed category name, as plugin saves settings under QtCreator application + category: "Qt 3D SceneEditor Content Geometry" + property alias leftPaneWidth: entityLibrary.width + property alias rightPaneWidth: propertyPane.width + property alias entityTreeHeight: entityTree.height + } + + Settings { + category: "Qt 3D SceneEditor Folders" + property alias saveFolder: editorContent.saveFolder + property alias textureFolder: editorContent.textureFolder + property alias importFolder: editorContent.importFolder + property alias defaultFolder: editorContent.defaultFolder + } + + EditorToolbar { + id: editorToolbar + } + Item { + anchors.top: editorToolbar.bottom + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + + Item { + // This item is used to map global mouse position + id: applicationArea + anchors.fill: parent + } + + DragEntity { + id: dragEntityItem + } + + + FileDialog { + id: loadFileDialog + selectMultiple: false + selectExisting: true + title: qsTr("Load Scene") + editorScene.emptyString + nameFilters: [qsTr("Qt3D Scenes (*.qt3d.qrc)") + editorScene.emptyString] + onAccepted: { + if (editorScene.loadScene(fileUrl)) { + entityTree.selectSceneRoot() + editorContent.saveFolder = folder + editorContent.saveFileUrl = fileUrl + } + } + } + + FileDialog { + id: saveFileDialog + selectMultiple: false + selectExisting: false + property bool exiting: false + title: qsTr("Save Scene") + editorScene.emptyString + nameFilters: [qsTr("Qt3D Scenes (*.qt3d.qrc)") + editorScene.emptyString] + onAccepted: { + editorScene.saveScene(fileUrl) + editorContent.saveFolder = folder + editorContent.saveFileUrl = fileUrl + if (exiting) + Qt.quit() + } + } + + FileDialog { + id: importEntityDialog + selectMultiple: false + selectExisting: true + title: qsTr("Import Entity") + editorScene.emptyString + nameFilters: [qsTr("All files (*)") + editorScene.emptyString] + onAccepted: { + editorScene.undoHandler.createImportEntityCommand(fileUrl) + editorContent.importFolder = folder + } + } + + + Shortcut { + id: copyShortcut + sequence: StandardKey.Copy + onActivated: { + // Prevent copying multiselection (for now, at least) + if (!editorScene.multiSelection) + editorContent.copyEntity(editorContent.selectedEntityName) + } + } + + Shortcut { + id: cutShortcut + sequence: StandardKey.Cut + onActivated: { + // Prevent cutting multiselection (for now, at least) + if (!editorScene.multiSelection) + editorContent.cutEntity(editorContent.selectedEntityName, editorContent.selectedEntity) + } + } + + Shortcut { + id: pasteShortcut + sequence: StandardKey.Paste + onActivated: { + editorContent.pasteEntity() + } + } + + EditorScene { + id: editorScene + viewport: editorViewport + freeView: true + + onSelectionChanged: { + restoreSelection(selection) + } + + onMultiSelectionListChanged: { + restoreMultiSelection(editorScene.multiSelectionList) + } + + onErrorChanged: { + notification.title = qsTr("Error") + editorScene.emptyString + notification.text = error + notification.open() + } + + onMouseRightButtonReleasedWithoutDragging: { + entityTree.menu.popup() + } + + onClipboardOperationChanged: { + if (clipboardOperation === EditorScene.ClipboardNone) + editorContent.trackMousePosition = false + } + + function restoreSelection(entity) { + var index = editorScene.sceneModel.getModelIndex(entity) + selectIndex(index) + } + + function restoreMultiSelection(selectionList) { + // Deselect old ones + entityTree.view.selection.clear() + // Dig indexes of all selected entities and pass the selections to entitytree + for (var i = 0; i < selectionList.length; ++i) { + var index = editorScene.sceneModel.getModelIndexByName(multiSelectionList[i]) + entityTree.view.selection.select(index, ItemSelectionModel.Select) + expandTo(index) + } + } + + function selectIndex(index) { + expandTo(index) + entityTree.focusTree() + entityTree.view.selection.setCurrentIndex(index, ItemSelectionModel.ClearAndSelect) + } + + function expandTo(index) { + var target = index + do { + entityTree.view.expand(target) + target = target.parent + } while (target.valid) + } + } + + MessageDialog { + id: notification + icon: StandardIcon.Warning + } + + SettingsDialog { + id: settingsDialog + } + + MessageDialog { + id: closingDialog + icon: StandardIcon.Warning + standardButtons: StandardButton.Yes | StandardButton.No | StandardButton.Cancel + title: qsTr("Exit Qt 3D Scene Editor") + editorScene.emptyString + text: qsTr("There are unsaved changes.\nSave changes before exiting?") + + editorScene.emptyString + + onYes: { + if (editorContent.saveFileUrl == "") { + saveFileDialog.exiting = true + saveFileDialog.open() + // No previous autosave file, no need to delete anything + saveFileDialog.exiting = false + } else { + editorScene.saveScene(editorContent.saveFileUrl) + editorScene.deleteScene(editorContent.saveFileUrl, true) + Qt.quit() + } + } + + onNo: { + Qt.quit() + } + + // Cancel doesn't need to do anything + } + + MessageDialog { + id: saveUnsavedDialog + property bool newFile: false + icon: StandardIcon.Warning + standardButtons: StandardButton.Yes | StandardButton.No | StandardButton.Cancel + title: qsTr("Save changes?") + editorScene.emptyString + text: qsTr("There are unsaved changes.\nSave changes?") + + editorScene.emptyString + + onYes: { + if (editorContent.saveFileUrl == "") { + saveFileDialog.folder = editorContent.saveFolder + saveFileDialog.open() + // No previous autosave file, no need to delete anything + } else { + editorScene.saveScene(editorContent.saveFileUrl) + editorScene.deleteScene(editorContent.saveFileUrl, true) + } + } + + onNo: { + if (newFile) { + editorScene.resetScene() + showNormalYPlane() + editorContent.saveFileUrl = "" + } else { + loadFileDialog.folder = editorContent.saveFolder + loadFileDialog.open() + } + } + + // Cancel doesn't need to do anything + } + + + SplitView { + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + orientation: Qt.Horizontal + width: parent.width - propertyPane.visibleWidth + + // Entity library + EntityLibrary { + id: entityLibrary + z: 4 + Layout.minimumWidth: 100 + Layout.maximumWidth: editorContent.width - 10 + onCreateNewEntity: { + entityTree.selectSceneRoot() + entityTree.addNewEntity(entityType, xPos, yPos) + } + } + + Item { + Layout.fillWidth: true + Layout.minimumWidth: 100 + + EditorViewport { + id: editorViewport + anchors.fill: parent + scene: editorScene + + MouseArea { + id: viewportMouseArea + anchors.fill: parent + onPressed: { + entityTree.focusTree() + mouse.accepted = false + } + onEntered: entityTree.treeviewPasting = false + hoverEnabled: editorContent.trackMousePosition + onMouseYChanged: editorContent.mousePosY = mouseY + onMouseXChanged: editorContent.mousePosX = mouseX + } + + DropArea { + anchors.fill: parent + keys: [ "insertEntity" ] + onContainsDragChanged: { + dragEntityItem.visible = !containsDrag + } + } + DragHandle { + // This is the translate handle at the center of selection box + handleType: EditorScene.DragTranslate + baseZ: 3 // Make sure translate handle is on top of scale handles + color: "#c22555" + radius: height / 2 + handleIndex: 0 + } + DragHandle { + // This is the group/mesh center indicator handle + handleType: EditorScene.DragTranslate + baseZ: 3 // Make sure center handle is on top of scale handles + color: "blue" + radius: height / 2 + handleIndex: 1 + } + DragHandle { + handleType: EditorScene.DragRotate + baseZ: 3 // Make sure rotate handle is on top of scale handles + Image { + anchors.fill: parent + source: "images/rotate_handle.png" + } + color: "transparent" + } + // Each corner will have a separate drag handle + DragHandle { + handleType: EditorScene.DragScale + handleIndex: 0 + } + DragHandle { + handleType: EditorScene.DragScale + handleIndex: 1 + } + DragHandle { + handleType: EditorScene.DragScale + handleIndex: 2 + } + DragHandle { + handleType: EditorScene.DragScale + handleIndex: 3 + } + DragHandle { + handleType: EditorScene.DragScale + handleIndex: 4 + } + DragHandle { + handleType: EditorScene.DragScale + handleIndex: 5 + } + DragHandle { + handleType: EditorScene.DragScale + handleIndex: 6 + } + DragHandle { + handleType: EditorScene.DragScale + handleIndex: 7 + } + + // Debug handle for visualizing world positions, uncomment to use. + // You can show debug handles with EditorScene::showDebugHandle(). + // DragHandle { + // handleType: EditorScene.DragDebug + // color: "green" + // baseZ: 4 + // } + } + } + } + + SplitView { + id: propertyPane + orientation: Qt.Vertical + anchors.top: parent.top + anchors.bottom: parent.bottom + width: editorContent.width / 4.5 + x: editorContent.width - visibleWidth + + property int visibleWidth: width + + // Entity list + EntityTree { + id: entityTree + } + + GeneralPropertyView { + id: generalPropertyView + entityName: editorContent.selectedEntityName + entityType: editorScene.sceneModel.editorSceneItemFromIndex(entityTree.view.selection.currentIndex).itemType() + propertiesButtonVisible: { + (entityTree.view.selection.currentIndex + !== editorScene.sceneModel.sceneEntityIndex()) + ? true : false + } + } + + // Property (transform, material, etc.) list + ListView { + id: componentPropertiesView + Layout.fillHeight: true + delegate: ComponentPropertiesDelegate {} + flickableDirection: Flickable.VerticalFlick + boundsBehavior: Flickable.StopAtBounds + clip: true + visible: generalPropertyView.viewTitleVisible + } + } + + onWidthChanged: { + var maximumWidth = editorContent.width - entityLibrary.width - 10 + if (propertyPane.visibleWidth > maximumWidth) { + propertyPane.visibleWidth = maximumWidth + propertyPane.width = propertyPane.visibleWidth + } else if (propertyPane.visibleWidth > resizeRectangle.paneMinimumWidth) { + propertyPane.width = propertyPane.visibleWidth + } + propertyPane.x = editorContent.width - propertyPane.visibleWidth + } + + Rectangle { + id: resizeRectangle + width: 2 + height: propertyPane.height + anchors.top: parent.top + anchors.right: propertyPane.left + color: editorContent.viewBorderColor + + property int paneMinimumWidth: 250 + property int paneMaximumWidth: editorContent.width - entityLibrary.width - 10 + + MouseArea { + anchors.fill: parent + hoverEnabled: true + + drag { + target: parent; + axis: Drag.XAxis + } + + onEntered: { + cursorShape = Qt.SplitHCursor + } + + onExited: { + cursorShape = Qt.ArrowCursor + } + + onMouseXChanged: { + if (drag.active) { + var newPaneWidth = propertyPane.width - mouseX + if (propertyPane.visibleWidth < resizeRectangle.paneMinimumWidth + || newPaneWidth < resizeRectangle.paneMinimumWidth) { + var newXPos = propertyPane.x + mouseX + if (newXPos < editorContent.width) { + propertyPane.visibleWidth = editorContent.width - newXPos + propertyPane.x = newXPos + } + } + else if (newPaneWidth > resizeRectangle.paneMinimumWidth + && newPaneWidth < resizeRectangle.paneMaximumWidth) { + propertyPane.x = editorContent.width - newPaneWidth + propertyPane.width = newPaneWidth + propertyPane.visibleWidth = propertyPane.width + } + } + } + } + } + + Timer { + id: autoSaveTimer + running: false + interval: 600000 // 10 minutes + repeat: true + onTriggered: { + editorScene.saveScene(editorContent.saveFileUrl, true) + } + } + + function resetCameraToDefault() { + editorScene.freeView = true + editorScene.resetFreeViewCamera() + } + + } +} + diff --git a/editorlib/qml/EditorToolbar.qml b/editorlib/qml/EditorToolbar.qml index af3e8b1..8f708fc 100644 --- a/editorlib/qml/EditorToolbar.qml +++ b/editorlib/qml/EditorToolbar.qml @@ -43,7 +43,7 @@ Item { padding.left: 0 background: Rectangle { implicitHeight: newButton.height - color: mainwindow.itemBackgroundColor + color: editorContent.itemBackgroundColor } } @@ -54,12 +54,12 @@ Item { id: newButton enabledIconSource: "images/new.png" tooltip: qsTr("New") + editorScene.emptyString - onEnabledButtonClicked: mainwindow.fileNew() + onEnabledButtonClicked: editorContent.fileNew() } ToolbarButton { enabledIconSource: "images/load.png" tooltip: qsTr("Load (Ctrl + O)") + editorScene.emptyString - onEnabledButtonClicked: mainwindow.fileLoad() + onEnabledButtonClicked: editorContent.fileLoad() } ToolbarButton { enabledIconSource: "images/import.png" @@ -67,7 +67,7 @@ Item { tooltip: qsTr("Import Entity") + editorScene.emptyString buttonEnabled: !editorScene.sceneModel.importEntityInProgress onEnabledButtonClicked: { - importEntityDialog.folder = mainwindow.importFolder + importEntityDialog.folder = editorContent.importFolder importEntityDialog.open() } } @@ -77,12 +77,12 @@ Item { ToolbarButton { enabledIconSource: "images/save.png" tooltip: qsTr("Save") + editorScene.emptyString - onEnabledButtonClicked: mainwindow.fileSave() + onEnabledButtonClicked: editorContent.fileSave() } ToolbarButton { enabledIconSource: "images/save_as.png" tooltip: qsTr("Save As") + editorScene.emptyString - onEnabledButtonClicked: mainwindow.fileSaveAs() + onEnabledButtonClicked: editorContent.fileSaveAs() } ToolbarSeparator {} @@ -95,7 +95,7 @@ Item { : qsTr ("Undo '%1'").arg(editorScene.undoHandler.undoText) + editorScene.emptyString buttonEnabled: editorScene.undoHandler.canUndo - onEnabledButtonClicked: mainwindow.undo() + onEnabledButtonClicked: editorContent.undo() } ToolbarButton { enabledIconSource: "images/redo.png" @@ -105,7 +105,7 @@ Item { : qsTr ("Redo '%1'").arg(editorScene.undoHandler.redoText) + editorScene.emptyString buttonEnabled: editorScene.undoHandler.canRedo - onEnabledButtonClicked: mainwindow.redo() + onEnabledButtonClicked: editorContent.redo() } ToolbarSeparator {} @@ -113,34 +113,34 @@ Item { ToolbarButton { enabledIconSource: "images/helperplane_x_deselected.png" disabledIconSource: "images/helperplane_x_selected.png" - selectedBgColor: mainwindow.iconHighlightColor + selectedBgColor: editorContent.iconHighlightColor tooltip: qsTr("Normal X (Ctrl + 1)") + editorScene.emptyString - buttonEnabled: currentHelperPlane === 0 ? false : true - onEnabledButtonClicked: mainwindow.showNormalXPlane() + buttonEnabled: editorContent.currentHelperPlane === 0 ? false : true + onEnabledButtonClicked: editorContent.showNormalXPlane() } ToolbarButton { enabledIconSource: "images/helperplane_y_deselected.png" disabledIconSource: "images/helperplane_y_selected.png" - selectedBgColor: mainwindow.iconHighlightColor + selectedBgColor: editorContent.iconHighlightColor tooltip: qsTr("Normal Y (Ctrl + 2)") + editorScene.emptyString - buttonEnabled: currentHelperPlane === 1 ? false : true - onEnabledButtonClicked: mainwindow.showNormalYPlane() + buttonEnabled: editorContent.currentHelperPlane === 1 ? false : true + onEnabledButtonClicked: editorContent.showNormalYPlane() } ToolbarButton { enabledIconSource: "images/helperplane_z_deselected.png" disabledIconSource: "images/helperplane_z_selected.png" - selectedBgColor: mainwindow.iconHighlightColor + selectedBgColor: editorContent.iconHighlightColor tooltip: qsTr("Normal Z (Ctrl + 3)") + editorScene.emptyString - buttonEnabled: currentHelperPlane === 2 ? false : true - onEnabledButtonClicked: mainwindow.showNormalZPlane() + buttonEnabled: editorContent.currentHelperPlane === 2 ? false : true + onEnabledButtonClicked: editorContent.showNormalZPlane() } ToolbarButton { enabledIconSource: "images/helperplane_none_deselected.png" disabledIconSource: "images/helperplane_none_selected.png" - selectedBgColor: mainwindow.iconHighlightColor + selectedBgColor: editorContent.iconHighlightColor tooltip: qsTr("Hide helper plane (Ctrl + 4)") + editorScene.emptyString - buttonEnabled: currentHelperPlane === 3 ? false : true - onEnabledButtonClicked: mainwindow.hideHelperPlane() + buttonEnabled: editorContent.currentHelperPlane === 3 ? false : true + onEnabledButtonClicked: editorContent.hideHelperPlane() } ToolbarSeparator {} @@ -157,7 +157,7 @@ Item { disabledIconSource: "images/reset_camera_to_default.png" pressedIconSource: "images/reset_camera_to_default_pressed.png" tooltip: qsTr("Reset to default position (Ctrl + 0)") + editorScene.emptyString - onEnabledButtonClicked: mainwindow.resetCameraToDefault() + onEnabledButtonClicked: editorContent.resetCameraToDefault() } StyledCheckBox { id: freeViewCheckBox @@ -188,7 +188,7 @@ Item { anchors.leftMargin: 8 anchors.bottomMargin: 4 anchors.verticalCenter: parent.verticalCenter - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight currentIndex: editorScene.activeSceneCameraIndex model: editorScene.sceneCamerasModel @@ -216,59 +216,59 @@ Item { Shortcut { id: fileNewShortcut sequence: StandardKey.New - onActivated: mainwindow.fileNew() + onActivated: editorContent.fileNew() } Shortcut { id: fileLoadShortcut sequence: StandardKey.Open - onActivated: mainwindow.fileLoad() + onActivated: editorContent.fileLoad() } Shortcut { id: fileSaveShortcut sequence: StandardKey.Save - onActivated: mainwindow.fileSave() + onActivated: editorContent.fileSave() } Shortcut { id: fileSaveAsShortcut sequence: StandardKey.SaveAs - onActivated: mainwindow.fileSaveAs() + onActivated: editorContent.fileSaveAs() } Shortcut { id: undoShortcut sequence: StandardKey.Undo - onActivated: mainwindow.undo() + onActivated: editorContent.undo() } Shortcut { id: redoShortcut sequence: StandardKey.Redo - onActivated: mainwindow.redo() + onActivated: editorContent.redo() } Shortcut { id: resetCameraShortcut sequence: "Ctrl+0" - onActivated: mainwindow.resetCameraToDefault() + onActivated: editorContent.resetCameraToDefault() } Shortcut { id: normalXShortcut sequence: "Ctrl+1" - onActivated: mainwindow.showNormalXPlane() + onActivated: editorContent.showNormalXPlane() } Shortcut { id: normalYShortcut sequence: "Ctrl+2" - onActivated: mainwindow.showNormalYPlane() + onActivated: editorContent.showNormalYPlane() } Shortcut { id: normalZShortcut sequence: "Ctrl+3" - onActivated: mainwindow.showNormalZPlane() + onActivated: editorContent.showNormalZPlane() } Shortcut { id: hideHelperPlaneShortcut sequence: "Ctrl+4" - onActivated: mainwindow.hideHelperPlane() + onActivated: editorContent.hideHelperPlane() } Shortcut { id: snapToActiveCameraShortcut diff --git a/editorlib/qml/EntityLibrary.qml b/editorlib/qml/EntityLibrary.qml index 538c032..abcc5ae 100644 --- a/editorlib/qml/EntityLibrary.qml +++ b/editorlib/qml/EntityLibrary.qml @@ -59,8 +59,8 @@ Item { anchors.top: entityViewHeader.bottom height: entityLibrary.height - entityViewHeader.height width: parent.width - color: mainwindow.paneBackgroundColor - border.color: mainwindow.viewBorderColor + color: editorContent.paneBackgroundColor + border.color: editorContent.viewBorderColor visible: entityViewHeader.viewVisible ScrollView { anchors.fill: parent @@ -79,7 +79,7 @@ Item { style: ButtonStyle { background: Rectangle { border.width: 0 - color: mainwindow.itemBackgroundColor + color: editorContent.itemBackgroundColor } } tooltip: qsTr("You can click here or drag'n'drop to add a new <i>%1</i> to the scene.").arg( @@ -95,10 +95,10 @@ Item { Text { text: meshString anchors.horizontalCenter: parent.horizontalCenter - color: mainwindow.textColor - font.family: mainwindow.labelFontFamily - font.weight: mainwindow.labelFontWeight - font.pixelSize: mainwindow.labelFontPixelSize + color: editorContent.textColor + font.family: editorContent.labelFontFamily + font.weight: editorContent.labelFontWeight + font.pixelSize: editorContent.labelFontPixelSize } } MouseArea { diff --git a/editorlib/qml/EntityModel.qml b/editorlib/qml/EntityModel.qml index 3d19702..55104aa 100644 --- a/editorlib/qml/EntityModel.qml +++ b/editorlib/qml/EntityModel.qml @@ -29,7 +29,7 @@ import QtQuick 2.5 import com.theqtcompany.SceneEditor3D 1.0 ListModel { - property string language: systemLanguage + property string language: editorContent.systemLanguage function retranslateUi() { setProperty(0, "meshString", qsTr("Cube")) diff --git a/editorlib/qml/EntityTree.qml b/editorlib/qml/EntityTree.qml index 81c7363..80b3069 100644 --- a/editorlib/qml/EntityTree.qml +++ b/editorlib/qml/EntityTree.qml @@ -52,7 +52,7 @@ Item { } else { // Doublecheck that we don't try to remove the scene root if (entityTreeView.selection.currentIndex !== editorScene.sceneModel.sceneEntityIndex()) - editorScene.undoHandler.createRemoveEntityCommand(selectedEntityName) + editorScene.undoHandler.createRemoveEntityCommand(editorContent.selectedEntityName) } } @@ -78,7 +78,7 @@ Item { // Never allow inserting to root if (entityTreeView.selection.currentIndex.row === -1) selectSceneRoot() - editorScene.undoHandler.createInsertEntityCommand(entityType, selectedEntityName, + editorScene.undoHandler.createInsertEntityCommand(entityType, editorContent.selectedEntityName, editorScene.getWorldPosition(x, y)) var newItemIndex = editorScene.sceneModel.lastInsertedIndex() @@ -125,10 +125,10 @@ Item { alternatingRowColors: false backgroundVisible: false style: TreeViewStyle { - textColor: mainwindow.textColor - highlightedTextColor: mainwindow.textColor - backgroundColor: mainwindow.paneBackgroundColor - alternateBackgroundColor: mainwindow.paneBackgroundColor + textColor: editorContent.textColor + highlightedTextColor: editorContent.textColor + backgroundColor: editorContent.paneBackgroundColor + alternateBackgroundColor: editorContent.paneBackgroundColor branchDelegate: Item { width: 10 height: 10 @@ -153,13 +153,13 @@ Item { implicitWidth: 14 anchors.bottom: parent.bottom anchors.top: parent.top - color: mainwindow.selectionColor + color: editorContent.selectionColor } } scrollBarBackground: Rectangle { implicitWidth: 20 implicitHeight: 30 - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor } decrementControl: Image { width: 20 @@ -357,7 +357,7 @@ Item { Rectangle { id: dragHighlight anchors.fill: parent - color: mainwindow.selectionColor + color: editorContent.selectionColor visible: false } } @@ -365,7 +365,7 @@ Item { Text { id: valueField anchors.verticalCenter: parent.verticalCenter - color: mainwindow.textColor + color: editorContent.textColor elide: styleData.elideMode text: styleData.value visible: true @@ -375,8 +375,8 @@ Item { Rectangle { id: renameField anchors.fill: parent - color: mainwindow.paneBackgroundColor - border.color: mainwindow.listHighlightColor + color: editorContent.paneBackgroundColor + border.color: editorContent.listHighlightColor visible: !valueField.visible TextInput { id: renameTextiInput @@ -385,12 +385,12 @@ Item { visible: !valueField.visible selectByMouse: true focus: visible - color: mainwindow.textColor - selectionColor: mainwindow.selectionColor - selectedTextColor: mainwindow.textColor - font.family: mainwindow.labelFontFamily - font.weight: mainwindow.labelFontWeight - font.pixelSize: mainwindow.labelFontPixelSize + color: editorContent.textColor + selectionColor: editorContent.selectionColor + selectedTextColor: editorContent.textColor + font.family: editorContent.labelFontFamily + font.weight: editorContent.labelFontWeight + font.pixelSize: editorContent.labelFontPixelSize validator: RegExpValidator { regExp: /^[A-Za-z_][A-Za-z0-9_ ]*$/ } @@ -407,10 +407,10 @@ Item { Keys.onReturnPressed: { valueField.visible = true if (text !== model.name) { - editorScene.undoHandler.createRenameEntityCommand(selectedEntityName, + editorScene.undoHandler.createRenameEntityCommand(editorContent.selectedEntityName, text) } - selectedEntityName = editorScene.sceneModel.entityName( + editorContent.selectedEntityName = editorScene.sceneModel.entityName( entityTreeView.selection.currentIndex) } Connections { @@ -468,28 +468,28 @@ Item { // If there is no current item selected for some reason, fall back to scene root, // except when dealing with multiselection, during which currentIndex can become -1 temporarily. if (entityTreeView.selection.currentIndex.row === -1) { - selectedEntityName = "" + editorContent.selectedEntityName = "" if (!editorScene.multiSelection) selectSceneRoot() } else { entityTreeView.sceneRootSelected = (editorScene.sceneModel.sceneEntityIndex() === entityTreeView.selection.currentIndex) - selectedEntity = editorScene.sceneModel.editorSceneItemFromIndex(entityTreeView.selection.currentIndex) - if (selectedEntity) { - componentPropertiesView.model = selectedEntity.componentsModel + editorContent.selectedEntity = editorScene.sceneModel.editorSceneItemFromIndex(entityTreeView.selection.currentIndex) + if (editorContent.selectedEntity) { + componentPropertiesView.model = editorContent.selectedEntity.componentsModel entityTreeView.cameraSelected = - selectedEntity.itemType() === EditorSceneItem.Camera + editorContent.selectedEntity.itemType() === EditorSceneItem.Camera entityTreeView.groupSelected = - selectedEntity.itemType() === EditorSceneItem.Group - selectedEntityName = editorScene.sceneModel.entityName( + editorContent.selectedEntity.itemType() === EditorSceneItem.Group + editorContent.selectedEntityName = editorScene.sceneModel.entityName( entityTreeView.selection.currentIndex) } else { // Should never get here - selectedEntityName = "" + editorContent.selectedEntityName = "" selectSceneRoot() } if (!editorScene.multiSelection) - editorScene.selection = selectedEntity.entity() + editorScene.selection = editorContent.selectedEntity.entity() } } } diff --git a/editorlib/qml/GeneralPropertyView.qml b/editorlib/qml/GeneralPropertyView.qml index d6e0be7..6447b4d 100644 --- a/editorlib/qml/GeneralPropertyView.qml +++ b/editorlib/qml/GeneralPropertyView.qml @@ -107,9 +107,9 @@ Item { onDesiredTextChanged: { if (desiredText !== "") { - editorScene.undoHandler.createRenameEntityCommand(selectedEntityName, + editorScene.undoHandler.createRenameEntityCommand(editorContent.selectedEntityName, desiredText) - selectedEntityName = editorScene.sceneModel.entityName(entityTree.view.selection.currentIndex) + editorContent.selectedEntityName = editorScene.sceneModel.entityName(entityTree.view.selection.currentIndex) } } @@ -146,9 +146,9 @@ Item { enabledIconSource: "images/property_light_shown.png" disabledIconSource: "images/property_light_hidden.png" tooltip: qsTr("Show/Hide Light Properties") + editorScene.emptyString - buttonEnabled: lightViewVisible + buttonEnabled: editorContent.lightViewVisible onEnabledButtonClicked: { - lightViewVisible = !lightViewVisible + editorContent.lightViewVisible = !editorContent.lightViewVisible } visible: (entityType === EditorSceneItem.Light) ? true : false } @@ -159,9 +159,9 @@ Item { enabledIconSource: "images/property_mesh_shown.png" disabledIconSource: "images/property_mesh_hidden.png" tooltip: qsTr("Show/Hide Mesh Properties") + editorScene.emptyString - buttonEnabled: meshViewVisible + buttonEnabled: editorContent.meshViewVisible onEnabledButtonClicked: { - meshViewVisible = !meshViewVisible + editorContent.meshViewVisible = !editorContent.meshViewVisible } visible: (entityType === EditorSceneItem.Mesh) ? true : false } @@ -172,9 +172,9 @@ Item { enabledIconSource: "images/property_transform_shown.png" disabledIconSource: "images/property_transform_hidden.png" tooltip: qsTr("Show/Hide Transform Properties") + editorScene.emptyString - buttonEnabled: transformViewVisible + buttonEnabled: editorContent.transformViewVisible onEnabledButtonClicked: { - transformViewVisible = !transformViewVisible + editorContent.transformViewVisible = !editorContent.transformViewVisible } visible: (entityType === EditorSceneItem.Mesh || entityType === EditorSceneItem.Light @@ -187,9 +187,9 @@ Item { enabledIconSource: "images/property_material_shown.png" disabledIconSource: "images/property_material_hidden.png" tooltip: qsTr("Show/Hide Material Properties") + editorScene.emptyString - buttonEnabled: materialViewVisible + buttonEnabled: editorContent.materialViewVisible onEnabledButtonClicked: { - materialViewVisible = !materialViewVisible + editorContent.materialViewVisible = !editorContent.materialViewVisible } visible: (entityType === EditorSceneItem.Mesh) ? true : false } @@ -200,9 +200,9 @@ Item { enabledIconSource: "images/property_camera_shown.png" disabledIconSource: "images/property_camera_hidden.png" tooltip: qsTr("Show/Hide Camera Properties") + editorScene.emptyString - buttonEnabled: cameraViewVisible + buttonEnabled: editorContent.cameraViewVisible onEnabledButtonClicked: { - cameraViewVisible = !cameraViewVisible + editorContent.cameraViewVisible = !editorContent.cameraViewVisible } visible: (entityType === EditorSceneItem.Camera) ? true : false } diff --git a/editorlib/qml/LightComponentDelegate.qml b/editorlib/qml/LightComponentDelegate.qml index f504e40..097a4f2 100644 --- a/editorlib/qml/LightComponentDelegate.qml +++ b/editorlib/qml/LightComponentDelegate.qml @@ -35,14 +35,14 @@ ComponentDelegate { property int currentLight: 0 - viewTitleVisible: lightViewVisible + viewTitleVisible: editorContent.lightViewVisible onChangeViewVisibity: { - lightViewVisible = viewVisibility + editorContent.lightViewVisible = viewVisibility } Component.onCompleted: { - if (!lightViewVisible) + if (!editorContent.lightViewVisible) height = minimumComponentHeight } @@ -61,11 +61,11 @@ ComponentDelegate { anchors.leftMargin: 8 anchors.bottomMargin: 4 anchors.verticalCenter: parent.verticalCenter - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight property int validIndex: -1 model: ListModel { - property string language: systemLanguage + property string language: editorContent.systemLanguage function retranslateUi() { // Repopulate list to change the current text as well diff --git a/editorlib/qml/MaterialComponentDelegate.qml b/editorlib/qml/MaterialComponentDelegate.qml index 7a154fe..294c481 100644 --- a/editorlib/qml/MaterialComponentDelegate.qml +++ b/editorlib/qml/MaterialComponentDelegate.qml @@ -36,14 +36,14 @@ ComponentDelegate { property int currentMaterial: 0 - viewTitleVisible: materialViewVisible + viewTitleVisible: editorContent.materialViewVisible onChangeViewVisibity: { - materialViewVisible = viewVisibility + editorContent.materialViewVisible = viewVisibility } Component.onCompleted: { - if (!materialViewVisible) + if (!editorContent.materialViewVisible) height = minimumComponentHeight } @@ -74,11 +74,11 @@ ComponentDelegate { anchors.bottomMargin: 4 anchors.verticalCenter: parent.verticalCenter property int validIndex: -1 - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight visible: materialComponentDelegate.currentMaterial !== EditorSceneItemMaterialComponentsModel.Unknown model: ListModel { - property string language: systemLanguage + property string language: editorContent.systemLanguage function retranslateUi() { clear() diff --git a/editorlib/qml/MeshComponentDelegate.qml b/editorlib/qml/MeshComponentDelegate.qml index 3f26147..41f642b 100644 --- a/editorlib/qml/MeshComponentDelegate.qml +++ b/editorlib/qml/MeshComponentDelegate.qml @@ -35,14 +35,14 @@ ComponentDelegate { property int currentMesh: 0 - viewTitleVisible: meshViewVisible + viewTitleVisible: editorContent.meshViewVisible onChangeViewVisibity: { - meshViewVisible = viewVisibility + editorContent.meshViewVisible = viewVisibility } Component.onCompleted: { - if (!meshViewVisible) + if (!editorContent.meshViewVisible) height = minimumComponentHeight } @@ -72,12 +72,12 @@ ComponentDelegate { anchors.leftMargin: 8 anchors.bottomMargin: 4 anchors.verticalCenter: parent.verticalCenter - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight property int validIndex: -1 visible: meshDelegate.currentMesh !== EditorSceneItemMeshComponentsModel.Unknown model: ListModel { - property string language: systemLanguage + property string language: editorContent.systemLanguage function retranslateUi() { clear() diff --git a/editorlib/qml/PluginMain.qml b/editorlib/qml/PluginMain.qml new file mode 100644 index 0000000..5570c4b --- /dev/null +++ b/editorlib/qml/PluginMain.qml @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D Editor of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.5 + +Rectangle { + color: editorContent.paneBackgroundColor + + EditorContent { + id: editorContent + } +} diff --git a/editorlib/qml/SettingsDialog.qml b/editorlib/qml/SettingsDialog.qml index 50d18d5..15d4a16 100644 --- a/editorlib/qml/SettingsDialog.qml +++ b/editorlib/qml/SettingsDialog.qml @@ -37,7 +37,7 @@ Window { modality: Qt.WindowModal width: 400 height: 320 - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor minimumHeight: settingsLayout.Layout.minimumHeight + buttonRow.Layout.minimumHeight minimumWidth: buttonRow.Layout.minimumWidth property bool previousAutoSaveEnabled @@ -166,7 +166,7 @@ Window { } StyledButton { implicitWidth: parent.width - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight text: folderPath onButtonClicked: fileDialog.open() } @@ -175,7 +175,7 @@ Window { FileDialog { id: fileDialog - folder: mainwindow.defaultFolder + folder: editorContent.defaultFolder title: defaultFolderLabel.text selectFolder: true onAccepted: { @@ -188,7 +188,7 @@ Window { id: separator width: parent.width height: 1 - color: mainwindow.listHighlightColor + color: editorContent.listHighlightColor anchors.bottom: buttonRow.top anchors.bottomMargin: 8 anchors.topMargin: 8 @@ -235,7 +235,7 @@ Window { } if (previousFolder.length > 0 && currentFolder !== previousFolder) { - mainwindow.defaultFolder = previousFolder + editorContent.defaultFolder = previousFolder currentFolder = previousFolder parseFolderString(currentFolder) } @@ -266,7 +266,7 @@ Window { autoSaveEnabled = saveCheckBox.checked if (autoSaveEnabled !== previousAutoSaveEnabled) { if (autoSaveEnabled) { - if (saveFileUrl == "") + if (editorContent.saveFileUrl == "") saveFileDialog.open() autoSaveTimer.start() } else { @@ -284,11 +284,11 @@ Window { function setFolder() { if (previousFolder !== currentFolder) { - mainwindow.defaultFolder = currentFolder + editorContent.defaultFolder = currentFolder // When default folder is changed, reset all saved folders - mainwindow.importFolder = currentFolder - mainwindow.saveFolder = currentFolder - mainwindow.textureFolder = currentFolder + editorContent.importFolder = currentFolder + editorContent.saveFolder = currentFolder + editorContent.textureFolder = currentFolder } } @@ -303,7 +303,7 @@ Window { currentGridSize = editorScene.gridSize previousGridSize = currentGridSize gridSizeSpinBox.value = currentGridSize - currentFolder = mainwindow.defaultFolder + currentFolder = editorContent.defaultFolder previousFolder = currentFolder parseFolderString(currentFolder) previousAutoSaveEnabled = autoSaveTimer.running diff --git a/editorlib/qml/StandaloneMain.qml b/editorlib/qml/StandaloneMain.qml new file mode 100644 index 0000000..ddfa8a8 --- /dev/null +++ b/editorlib/qml/StandaloneMain.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D Editor of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.5 +import QtQuick.Controls 2.0 as QQC2 +import Qt.labs.settings 1.0 +import com.theqtcompany.SceneEditor3D 1.0 + +QQC2.ApplicationWindow { + id: standaloneWindow + title: qsTr("Qt 3D Scene Editor") + editorContent.editorScene.emptyString + editorContent.saveFileTitleAddition + width: 1280 + height: 800 + visible: false + color: editorContent.paneBackgroundColor + minimumHeight: 400 + minimumWidth: 640 + + EditorContent { + id: editorContent + visible: false + } + + onClosing: { + close.accepted = editorContent.checkUnsavedChanges() + } + + Component.onCompleted: { + Qt.application.organization = "The Qt Company" + Qt.application.domain = "qt.io" + Qt.application.name = "Qt 3D Scene Editor" + // Redraw everything to get rid of artifacts + showMaximized() + show() + editorContent.visible = true + } + + Settings { + // Save window placement, size + category: "Qt 3D SceneEditor Window" + property alias x: standaloneWindow.x + property alias y: standaloneWindow.y + property alias width: standaloneWindow.width + property alias height: standaloneWindow.height + } +} diff --git a/editorlib/qml/ToolbarButton.qml b/editorlib/qml/ToolbarButton.qml index abfe1aa..c294929 100644 --- a/editorlib/qml/ToolbarButton.qml +++ b/editorlib/qml/ToolbarButton.qml @@ -31,7 +31,7 @@ EnableButton { height: 32 width: 32 anchors.verticalCenter: parent.verticalCenter - hoveredBgColor: mainwindow.listHighlightColor - selectedBgColor: buttonEnabled === true ? mainwindow.iconHighlightColor : "transparent" + hoveredBgColor: editorContent.listHighlightColor + selectedBgColor: buttonEnabled === true ? editorContent.iconHighlightColor : "transparent" buttonEnabled: true } diff --git a/editorlib/qml/ToolbarSeparator.qml b/editorlib/qml/ToolbarSeparator.qml index ac51e07..7028613 100644 --- a/editorlib/qml/ToolbarSeparator.qml +++ b/editorlib/qml/ToolbarSeparator.qml @@ -31,7 +31,7 @@ Rectangle { id: menuSeparator height: 24 width: 1 - color: mainwindow.listHighlightColor - border.color: mainwindow.itemBackgroundColor + color: editorContent.listHighlightColor + border.color: editorContent.itemBackgroundColor border.width: 1 } diff --git a/editorlib/qml/TransformComponentDelegate.qml b/editorlib/qml/TransformComponentDelegate.qml index 2bf7816..8df9c86 100644 --- a/editorlib/qml/TransformComponentDelegate.qml +++ b/editorlib/qml/TransformComponentDelegate.qml @@ -36,21 +36,21 @@ ComponentDelegate { property int currentTransform: 0 property bool fieldsDisabled: transformFieldsDisabled - viewTitleVisible: transformViewVisible + viewTitleVisible: editorContent.transformViewVisible componentType: EditorSceneItemComponentsModel.Transform onChangeViewVisibity: { - transformViewVisible = viewVisibility + editorContent.transformViewVisible = viewVisibility } onFieldsDisabledChanged: { - selectedEntity.setCustomProperty(editorScene.sceneModel.editorSceneItemFromIndex(entityTree.view.selection.currentIndex).entity(), + editorContent.selectedEntity.setCustomProperty(editorScene.sceneModel.editorSceneItemFromIndex(entityTree.view.selection.currentIndex).entity(), editorScene.lockTransformPropertyName, fieldsDisabled) } Component.onCompleted: { - if (!transformViewVisible) + if (!editorContent.transformViewVisible) height = minimumComponentHeight } @@ -68,12 +68,12 @@ ComponentDelegate { anchors.leftMargin: 8 anchors.bottomMargin: 4 anchors.verticalCenter: parent.verticalCenter - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight enabled: !fieldsDisabled property int validIndex: -1 model: ListModel { - property string language: systemLanguage + property string language: editorContent.systemLanguage function retranslateUi() { clear() diff --git a/editorlib/qml/inputfields/CheckBoxPropertyInputField.qml b/editorlib/qml/inputfields/CheckBoxPropertyInputField.qml index abf7242..214dfed 100644 --- a/editorlib/qml/inputfields/CheckBoxPropertyInputField.qml +++ b/editorlib/qml/inputfields/CheckBoxPropertyInputField.qml @@ -53,9 +53,9 @@ PropertyInputField { } Rectangle { - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor height: checkBoxInput.height - width: checkBox.width + mainwindow.controlMargin + width: checkBox.width + editorContent.controlMargin anchors.right: checkBox.right } diff --git a/editorlib/qml/inputfields/ColorPropertyInputField.qml b/editorlib/qml/inputfields/ColorPropertyInputField.qml index 7d30130..8d5dea1 100644 --- a/editorlib/qml/inputfields/ColorPropertyInputField.qml +++ b/editorlib/qml/inputfields/ColorPropertyInputField.qml @@ -89,9 +89,9 @@ PropertyInputField { } Rectangle { - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor implicitHeight: colorInput.height - implicitWidth: colorButton.width + mainwindow.controlMargin + implicitWidth: colorButton.width + editorContent.controlMargin anchors.right: colorButton.right } @@ -100,15 +100,15 @@ PropertyInputField { Layout.alignment: Qt.AlignRight anchors.right: lockButton.left anchors.rightMargin: 4 - implicitWidth: colorInput.width * 0.6 > mainwindow.maximumControlWidth - ? mainwindow.maximumControlWidth + implicitWidth: colorInput.width * 0.6 > editorContent.maximumControlWidth + ? editorContent.maximumControlWidth : colorInput.width * 0.6 - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight enabled: lockButton.buttonEnabled background: Rectangle { border.width: colorButton.activeFocus ? 2 : 1 - border.color: enabled ? mainwindow.listHighlightColor - : mainwindow.itemBackgroundColor + border.color: enabled ? editorContent.listHighlightColor + : editorContent.itemBackgroundColor color: enabled ? colorValue : Qt.rgba(colorValue.r, colorValue.g, colorValue.b, 0.5) } diff --git a/editorlib/qml/inputfields/FilePropertyInputField.qml b/editorlib/qml/inputfields/FilePropertyInputField.qml index b883361..773d6e4 100644 --- a/editorlib/qml/inputfields/FilePropertyInputField.qml +++ b/editorlib/qml/inputfields/FilePropertyInputField.qml @@ -53,7 +53,7 @@ PropertyInputField { title: fileLabel.text onAccepted: { handleEditingFinished(fileUrl) - mainwindow.importFolder = folder + editorContent.importFolder = folder } onRejected: { if (fileButton.text === "") @@ -74,9 +74,9 @@ PropertyInputField { } Rectangle { - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor height: fileLabel.height - width: mainwindow.controlMargin + width: editorContent.controlMargin anchors.right: fileButton.left } @@ -84,10 +84,10 @@ PropertyInputField { id: fileButton Layout.alignment: Qt.AlignRight implicitWidth: fileInput.width * 0.6 + 20 // Lockbutton width - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight text: url onClicked: { - fileDialog.folder = mainwindow.importFolder + fileDialog.folder = editorContent.importFolder fileDialog.open() } } diff --git a/editorlib/qml/inputfields/FloatPropertyInputField.qml b/editorlib/qml/inputfields/FloatPropertyInputField.qml index 85190b7..07e9b53 100644 --- a/editorlib/qml/inputfields/FloatPropertyInputField.qml +++ b/editorlib/qml/inputfields/FloatPropertyInputField.qml @@ -76,10 +76,10 @@ PropertyInputField { } Rectangle { - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor height: floatInput.height - width: floatInput.width * 0.6 > mainwindow.maximumControlWidth - ? mainwindow.maximumControlWidth + mainwindow.controlMargin + width: floatInput.width * 0.6 > editorContent.maximumControlWidth + ? editorContent.maximumControlWidth + editorContent.controlMargin : floatInput.width * 0.62 anchors.right: valueInput.right } @@ -89,10 +89,10 @@ PropertyInputField { anchors.right: lockButton.left anchors.rightMargin: 4 Layout.alignment: Qt.AlignRight - implicitWidth: floatInput.width * 0.6 > mainwindow.maximumControlWidth - ? mainwindow.maximumControlWidth + implicitWidth: floatInput.width * 0.6 > editorContent.maximumControlWidth + ? editorContent.maximumControlWidth : floatInput.width * 0.6 - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight to: maximum * roundMultiplier stepSize: step from: minimum * roundMultiplier diff --git a/editorlib/qml/inputfields/FloatSliderInputField.qml b/editorlib/qml/inputfields/FloatSliderInputField.qml index 851bf39..1dee997 100644 --- a/editorlib/qml/inputfields/FloatSliderInputField.qml +++ b/editorlib/qml/inputfields/FloatSliderInputField.qml @@ -91,10 +91,10 @@ Item { } Rectangle { - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor height: floatSliderInputField.height - width: floatSliderInputField.width * 0.6 > mainwindow.maximumControlWidth - ? mainwindow.maximumControlWidth + mainwindow.controlMargin + width: floatSliderInputField.width * 0.6 > editorContent.maximumControlWidth + ? editorContent.maximumControlWidth + editorContent.controlMargin : floatSliderInputField.width * 0.62 anchors.right: floatInput.right } @@ -107,8 +107,8 @@ Item { from: minimum to: maximum - implicitWidth: floatSliderInputField.width * 0.6 > mainwindow.maximumControlWidth - ? mainwindow.maximumControlWidth * 0.65 + implicitWidth: floatSliderInputField.width * 0.6 > editorContent.maximumControlWidth + ? editorContent.maximumControlWidth * 0.65 : floatSliderInputField.width * 0.4 - 4 enabled: lockButton.buttonEnabled anchors.right: floatInput.left @@ -123,11 +123,11 @@ Item { implicitWidth: 20 implicitHeight: 20 radius: width / 2 - border.color: enabled ? mainwindow.listHighlightColor - : mainwindow.itemBackgroundColor - color: enabled ? (slider.pressed ? mainwindow.selectionColor - : mainwindow.listHighlightColor) - : mainwindow.itemBackgroundColor + border.color: enabled ? editorContent.listHighlightColor + : editorContent.itemBackgroundColor + color: enabled ? (slider.pressed ? editorContent.selectionColor + : editorContent.listHighlightColor) + : editorContent.itemBackgroundColor readonly property bool horizontal: slider.orientation === Qt.Horizontal } @@ -139,9 +139,9 @@ Item { width: horizontal ? slider.availableWidth : implicitWidth height: horizontal ? implicitHeight : slider.availableHeight radius: 3 - border.color: enabled ? mainwindow.listHighlightColor - : mainwindow.itemBackgroundColor - color: enabled ? mainwindow.listHighlightColor : mainwindow.itemBackgroundColor + border.color: enabled ? editorContent.listHighlightColor + : editorContent.itemBackgroundColor + color: enabled ? editorContent.listHighlightColor : editorContent.itemBackgroundColor scale: horizontal && slider.mirrored ? -1 : 1 readonly property bool horizontal: slider.orientation === Qt.Horizontal @@ -182,8 +182,8 @@ Item { StyledTextField { id: floatInput - implicitWidth: floatSliderInputField.width * 0.6 > mainwindow.maximumControlWidth - ? mainwindow.maximumControlWidth * 0.34 + implicitWidth: floatSliderInputField.width * 0.6 > editorContent.maximumControlWidth + ? editorContent.maximumControlWidth * 0.34 : floatSliderInputField.width * 0.2 anchors.right: lockButton.left anchors.rightMargin: 4 diff --git a/editorlib/qml/inputfields/IntPropertyInputField.qml b/editorlib/qml/inputfields/IntPropertyInputField.qml index c5b9033..1c58368 100644 --- a/editorlib/qml/inputfields/IntPropertyInputField.qml +++ b/editorlib/qml/inputfields/IntPropertyInputField.qml @@ -64,10 +64,10 @@ PropertyInputField { } Rectangle { - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor height: intInput.height - width: intInput.width * 0.6 > mainwindow.maximumControlWidth - ? mainwindow.maximumControlWidth + mainwindow.controlMargin + width: intInput.width * 0.6 > editorContent.maximumControlWidth + ? editorContent.maximumControlWidth + editorContent.controlMargin : intInput.width * 0.62 anchors.right: valueInput.right } @@ -77,10 +77,10 @@ PropertyInputField { anchors.right: lockButton.left anchors.rightMargin: 4 Layout.alignment: Qt.AlignRight - implicitWidth: intInput.width * 0.6 > mainwindow.maximumControlWidth - ? mainwindow.maximumControlWidth + implicitWidth: intInput.width * 0.6 > editorContent.maximumControlWidth + ? editorContent.maximumControlWidth : intInput.width * 0.6 - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight to: 100 stepSize: 1 from: minimum diff --git a/editorlib/qml/inputfields/ModelRoleInputField.qml b/editorlib/qml/inputfields/ModelRoleInputField.qml index 4c48601..f900552 100644 --- a/editorlib/qml/inputfields/ModelRoleInputField.qml +++ b/editorlib/qml/inputfields/ModelRoleInputField.qml @@ -37,7 +37,7 @@ Item { function handleEditingFinished(newValue) { if (currentValue !== newValue) { editorScene.undoHandler.createChangeModelRoleCommand( - selectedEntityName, componentType, + editorContent.selectedEntityName, componentType, modelRole, newValue, currentValue, undoText); } } diff --git a/editorlib/qml/inputfields/PropertyInputField.qml b/editorlib/qml/inputfields/PropertyInputField.qml index 58a93a4..0f13b87 100644 --- a/editorlib/qml/inputfields/PropertyInputField.qml +++ b/editorlib/qml/inputfields/PropertyInputField.qml @@ -30,7 +30,7 @@ import com.theqtcompany.SceneEditor3D 1.0 Item { property string propertyName: "" - property string entityName: selectedEntityName + property string entityName: editorContent.selectedEntityName property var component: null property int componentType: EditorSceneItemComponentsModel.Unknown property var componentValue: (component === null) ? "" : component[propertyName] diff --git a/editorlib/qml/inputfields/PropertyLockButton.qml b/editorlib/qml/inputfields/PropertyLockButton.qml index a4b9e35..f218ef6 100644 --- a/editorlib/qml/inputfields/PropertyLockButton.qml +++ b/editorlib/qml/inputfields/PropertyLockButton.qml @@ -39,8 +39,8 @@ EnableButton { buttonEnabled: !locked Component.onCompleted: { - if (selectedEntity) { - var propertyLocked = selectedEntity.customProperty(lockComponent, lockProperty) + if (editorContent.selectedEntity) { + var propertyLocked = editorContent.selectedEntity.customProperty(lockComponent, lockProperty) if (propertyLocked != undefined) locked = propertyLocked } @@ -48,6 +48,6 @@ EnableButton { onEnabledButtonClicked: { locked = !locked - selectedEntity.setCustomProperty(lockComponent, lockProperty, locked) + editorContent.selectedEntity.setCustomProperty(lockComponent, lockProperty, locked) } } diff --git a/editorlib/qml/inputfields/SizePropertyInputField.qml b/editorlib/qml/inputfields/SizePropertyInputField.qml index f2eaec9..1077afc 100644 --- a/editorlib/qml/inputfields/SizePropertyInputField.qml +++ b/editorlib/qml/inputfields/SizePropertyInputField.qml @@ -69,8 +69,8 @@ PropertyInputField { id: row anchors.right: parent.right Layout.alignment: Qt.AlignRight - Layout.preferredWidth: sizeInput.width * 0.6 > mainwindow.maximumControlWidth - ? mainwindow.maximumControlWidth + Layout.preferredWidth: sizeInput.width * 0.6 > editorContent.maximumControlWidth + ? editorContent.maximumControlWidth : sizeInput.width * 0.6 property real columnSpacing: widthLabel.contentWidth != 0 ? 6 : 4 property real cellwidth: (Layout.preferredWidth @@ -79,10 +79,10 @@ PropertyInputField { Rectangle { - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor height: sizeInput.height - width: sizeInput.width * 0.6 > mainwindow.maximumControlWidth - ? mainwindow.maximumControlWidth + mainwindow.controlMargin + width: sizeInput.width * 0.6 > editorContent.maximumControlWidth + ? editorContent.maximumControlWidth + editorContent.controlMargin : sizeInput.width * 0.62 anchors.right: heightInput.right } diff --git a/editorlib/qml/inputfields/StyledButton.qml b/editorlib/qml/inputfields/StyledButton.qml index 793e1d5..aa40f15 100644 --- a/editorlib/qml/inputfields/StyledButton.qml +++ b/editorlib/qml/inputfields/StyledButton.qml @@ -40,9 +40,9 @@ Item { anchors.margins: 4 color: { if (mouseArea.containsPress) - mainwindow.iconHighlightColor + editorContent.iconHighlightColor else if (mouseArea.containsMouse) // hover - mainwindow.listHighlightColor + editorContent.listHighlightColor else "transparent" } @@ -52,10 +52,10 @@ Item { Text { id: buttonText anchors.centerIn: parent - color: mainwindow.textColor - font.family: mainwindow.labelFontFamily - font.weight: mainwindow.labelFontWeight - font.pixelSize: mainwindow.labelFontPixelSize + color: editorContent.textColor + font.family: editorContent.labelFontFamily + font.weight: editorContent.labelFontWeight + font.pixelSize: editorContent.labelFontPixelSize } MouseArea { diff --git a/editorlib/qml/inputfields/StyledCheckBox.qml b/editorlib/qml/inputfields/StyledCheckBox.qml index ebcdd52..5235fe0 100644 --- a/editorlib/qml/inputfields/StyledCheckBox.qml +++ b/editorlib/qml/inputfields/StyledCheckBox.qml @@ -39,7 +39,7 @@ QQC2.CheckBox { implicitHeight: 16 x: autoSaveCheckBox.leftPadding + (autoSaveCheckBox.availableWidth - width) / 2 y: autoSaveCheckBox.topPadding + (autoSaveCheckBox.availableHeight - height) / 2 - color: mainwindow.itemColor + color: editorContent.itemColor Image { x: (parent.width - width) / 2 diff --git a/editorlib/qml/inputfields/StyledLabel.qml b/editorlib/qml/inputfields/StyledLabel.qml index 968c484..4bb1d45 100644 --- a/editorlib/qml/inputfields/StyledLabel.qml +++ b/editorlib/qml/inputfields/StyledLabel.qml @@ -32,10 +32,10 @@ import QtQuick.Controls 2.0 as QQC2 QQC2.Label { property alias tooltip: button.tooltip - color: enabled ? mainwindow.textColor : mainwindow.disabledTextColor - font.family: mainwindow.labelFontFamily - font.weight: mainwindow.labelFontWeight - font.pixelSize: mainwindow.labelFontPixelSize + color: enabled ? editorContent.textColor : editorContent.disabledTextColor + font.family: editorContent.labelFontFamily + font.weight: editorContent.labelFontWeight + font.pixelSize: editorContent.labelFontPixelSize Button { id: button diff --git a/editorlib/qml/inputfields/StyledRadioButton.qml b/editorlib/qml/inputfields/StyledRadioButton.qml index ceb405a..a058d61 100644 --- a/editorlib/qml/inputfields/StyledRadioButton.qml +++ b/editorlib/qml/inputfields/StyledRadioButton.qml @@ -44,10 +44,10 @@ QQC2.RadioButton { radius: width / 2 border.width: 1 - border.color: radioButton.pressed ? mainwindow.listHighlightColor + border.color: radioButton.pressed ? editorContent.listHighlightColor : "#353637" - color: radioButton.pressed ? mainwindow.paneBackgroundColor - : mainwindow.itemColor + color: radioButton.pressed ? editorContent.paneBackgroundColor + : editorContent.itemColor Rectangle { x: (parent.width - width) / 2 @@ -55,8 +55,8 @@ QQC2.RadioButton { width: 14 height: 14 radius: width / 2 - color: radioButton.pressed ? mainwindow.textColor - : mainwindow.selectionColor + color: radioButton.pressed ? editorContent.textColor + : editorContent.selectionColor visible: radioButton.checked } } diff --git a/editorlib/qml/inputfields/StyledSpinBox.qml b/editorlib/qml/inputfields/StyledSpinBox.qml index 979789d..a0fc50d 100644 --- a/editorlib/qml/inputfields/StyledSpinBox.qml +++ b/editorlib/qml/inputfields/StyledSpinBox.qml @@ -30,13 +30,13 @@ import QtQuick.Controls 2.0 as QQC2 QQC2.SpinBox { id: control - font.family: mainwindow.labelFontFamily - font.weight: mainwindow.labelFontWeight - font.pixelSize: mainwindow.labelFontPixelSize + font.family: editorContent.labelFontFamily + font.weight: editorContent.labelFontWeight + font.pixelSize: editorContent.labelFontPixelSize background: Rectangle { - border.color: mainwindow.listHighlightColor - color: mainwindow.paneBackgroundColor + border.color: editorContent.listHighlightColor + color: editorContent.paneBackgroundColor } down.indicator: Rectangle { @@ -44,8 +44,8 @@ QQC2.SpinBox { height: parent.height implicitWidth: 40 implicitHeight: 40 - border.color: mainwindow.listHighlightColor - color: mainwindow.listHighlightColor + border.color: editorContent.listHighlightColor + color: editorContent.listHighlightColor Image { anchors.centerIn: parent source: "images/spinbox_down.png" @@ -57,8 +57,8 @@ QQC2.SpinBox { height: parent.height implicitWidth: 40 implicitHeight: 40 - border.color: mainwindow.listHighlightColor - color: mainwindow.listHighlightColor + border.color: editorContent.listHighlightColor + color: editorContent.listHighlightColor Image { anchors.centerIn: parent source: "images/spinbox_up.png" diff --git a/editorlib/qml/inputfields/StyledTextField.qml b/editorlib/qml/inputfields/StyledTextField.qml index e97c4cb..4f73158 100644 --- a/editorlib/qml/inputfields/StyledTextField.qml +++ b/editorlib/qml/inputfields/StyledTextField.qml @@ -30,10 +30,10 @@ import QtQuick.Controls 2.0 as QQC2 QQC2.TextField { background: TextFieldBackgroundStyle {} - color: mainwindow.textColor - selectionColor: mainwindow.selectionColor - selectedTextColor: mainwindow.textColor - font.family: mainwindow.labelFontFamily - font.weight: mainwindow.labelFontWeight - font.pixelSize: mainwindow.labelFontPixelSize + color: editorContent.textColor + selectionColor: editorContent.selectionColor + selectedTextColor: editorContent.textColor + font.family: editorContent.labelFontFamily + font.weight: editorContent.labelFontWeight + font.pixelSize: editorContent.labelFontPixelSize } diff --git a/editorlib/qml/inputfields/StyledTextInput.qml b/editorlib/qml/inputfields/StyledTextInput.qml index 9de568a..416a8c0 100644 --- a/editorlib/qml/inputfields/StyledTextInput.qml +++ b/editorlib/qml/inputfields/StyledTextInput.qml @@ -30,9 +30,9 @@ import QtQuick 2.5 TextInput { text: parent.textFromValue(parent.value, parent.locale) font: parent.font - color: mainwindow.textColor - selectionColor: mainwindow.selectionColor - selectedTextColor: mainwindow.textColor + color: editorContent.textColor + selectionColor: editorContent.selectionColor + selectedTextColor: editorContent.textColor horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter diff --git a/editorlib/qml/inputfields/TextFieldBackgroundStyle.qml b/editorlib/qml/inputfields/TextFieldBackgroundStyle.qml index 8a97498..18d6e88 100644 --- a/editorlib/qml/inputfields/TextFieldBackgroundStyle.qml +++ b/editorlib/qml/inputfields/TextFieldBackgroundStyle.qml @@ -28,6 +28,6 @@ import QtQuick 2.5 Rectangle { - color: parent.enabled ? mainwindow.paneBackgroundColor : "transparent" - border.color: parent.enabled ? mainwindow.listHighlightColor : "white" + color: parent.enabled ? editorContent.paneBackgroundColor : "transparent" + border.color: parent.enabled ? editorContent.listHighlightColor : "white" } diff --git a/editorlib/qml/inputfields/TextInputField.qml b/editorlib/qml/inputfields/TextInputField.qml index 308f1c3..dd4b646 100644 --- a/editorlib/qml/inputfields/TextInputField.qml +++ b/editorlib/qml/inputfields/TextInputField.qml @@ -61,9 +61,9 @@ Item { } Rectangle { - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor height: textLabel.height - implicitWidth: textInputCtrl.width + mainwindow.controlMargin + implicitWidth: textInputCtrl.width + editorContent.controlMargin anchors.right: textInputCtrl.right } diff --git a/editorlib/qml/inputfields/TextureInputField.qml b/editorlib/qml/inputfields/TextureInputField.qml index 0ec98d3..b490010 100644 --- a/editorlib/qml/inputfields/TextureInputField.qml +++ b/editorlib/qml/inputfields/TextureInputField.qml @@ -49,7 +49,7 @@ ModelRoleInputField { onAccepted: { fileInput.undoText = qsTr("Change texture") handleEditingFinished(fileUrl) - mainwindow.textureFolder = folder + editorContent.textureFolder = folder } } @@ -78,13 +78,13 @@ ModelRoleInputField { contentItem: Text { text: fileButton.text font: fileButton.font - color: mainwindow.itemBackgroundColor + color: editorContent.itemBackgroundColor horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter elide: Text.ElideRight } onClicked: { - fileDialog.folder = mainwindow.textureFolder + fileDialog.folder = editorContent.textureFolder fileDialog.open() } } @@ -95,7 +95,7 @@ ModelRoleInputField { Layout.preferredHeight: fileInput.height Layout.preferredWidth: Layout.preferredHeight Layout.alignment: Qt.AlignRight - border.color: listHighlightColor + border.color: editorContent.listHighlightColor border.width: 1 Image { source: url @@ -106,7 +106,7 @@ ModelRoleInputField { MouseArea { anchors.fill: parent onClicked: { - fileDialog.folder = mainwindow.textureFolder + fileDialog.folder = editorContent.textureFolder fileDialog.open() } } diff --git a/editorlib/qml/inputfields/Vector3DInputField.qml b/editorlib/qml/inputfields/Vector3DInputField.qml index 5d93751..a24e9e9 100644 --- a/editorlib/qml/inputfields/Vector3DInputField.qml +++ b/editorlib/qml/inputfields/Vector3DInputField.qml @@ -46,8 +46,8 @@ Item { property real minimum: -999999999 / roundMultiplier // TODO: Do we need more sensible default minimum? property real maximum: 999999999 / roundMultiplier // TODO: Do we need more sensible default maximum? property int step: roundMultiplier - property real inputCellWidth: vectorInput.width * 0.6 > mainwindow.maximumControlWidth - ? mainwindow.maximumControlWidth + property real inputCellWidth: vectorInput.width * 0.6 > editorContent.maximumControlWidth + ? editorContent.maximumControlWidth : vectorInput.width * 0.6 property string tooltip: "" property var tooltipArgs: ["", "", ""] @@ -93,9 +93,9 @@ Item { } Rectangle { - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor implicitHeight: xInput.height - implicitWidth: inputCellWidth + mainwindow.controlMargin + implicitWidth: inputCellWidth + editorContent.controlMargin anchors.right: xInput.right } @@ -105,7 +105,7 @@ Item { anchors.rightMargin: 4 Layout.alignment: Qt.AlignRight implicitWidth: inputCellWidth - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight to: maximum * roundMultiplier stepSize: step from: minimum * roundMultiplier @@ -159,9 +159,9 @@ Item { } Rectangle { - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor implicitHeight: yInput.height - implicitWidth: inputCellWidth + mainwindow.controlMargin + implicitWidth: inputCellWidth + editorContent.controlMargin anchors.right: yInput.right } @@ -171,7 +171,7 @@ Item { anchors.rightMargin: 4 Layout.alignment: Qt.AlignRight implicitWidth: inputCellWidth - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight to: maximum * roundMultiplier stepSize: step from: minimum * roundMultiplier @@ -223,9 +223,9 @@ Item { } Rectangle { - color: mainwindow.paneBackgroundColor + color: editorContent.paneBackgroundColor implicitHeight: zInput.height - implicitWidth: inputCellWidth + mainwindow.controlMargin + implicitWidth: inputCellWidth + editorContent.controlMargin anchors.right: zInput.right } @@ -235,7 +235,7 @@ Item { anchors.rightMargin: 4 Layout.alignment: Qt.AlignRight implicitWidth: inputCellWidth - implicitHeight: qlcControlHeight + implicitHeight: editorContent.qlcControlHeight to: maximum * roundMultiplier stepSize: step from: minimum * roundMultiplier diff --git a/editorlib/qml/main.qml b/editorlib/qml/main.qml deleted file mode 100644 index bc7c23f..0000000 --- a/editorlib/qml/main.qml +++ /dev/null @@ -1,707 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D Editor of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Layouts 1.2 -import QtQuick.Dialogs 1.2 -import QtQuick.Controls 2.0 as QQC2 -import QtQml.Models 2.2 -import QtQml 2.2 -import Qt3D.Core 2.0 -import Qt.labs.settings 1.0 -import com.theqtcompany.SceneEditor3D 1.0 - -QQC2.ApplicationWindow { - id: mainwindow - title: qsTr("Qt 3D Scene Editor") + editorScene.emptyString + saveFileTitleAddition - width: 1280 - height: 800 - visible: false - color: paneBackgroundColor - minimumHeight: 400 - minimumWidth: 640 - - Settings { - // Save window placement, size, and view panel sizes - // Use detailed category name, as plugin saves settings under QtCreator application - category: "Qt 3D SceneEditor Window" - property alias x: mainwindow.x - property alias y: mainwindow.y - property alias width: mainwindow.width - property alias height: mainwindow.height - property alias leftPaneWidth: entityLibrary.width - property alias rightPaneWidth: propertyPane.width - property alias entityTreeHeight: entityTree.height - } - - Settings { - category: "Qt 3D SceneEditor Folders" - property alias saveFolder: mainwindow.saveFolder - property alias textureFolder: mainwindow.textureFolder - property alias importFolder: mainwindow.importFolder - property alias defaultFolder: mainwindow.defaultFolder - } - - Item { - // This item is used to map global mouse position - id: applicationArea - anchors.fill: parent - } - - DragEntity { - id: dragEntityItem - } - - property var selectedEntity: null - property string selectedEntityName: "" - property var sceneModel: EditorSceneItemComponentsModel - property url saveFileUrl: "" - property url defaultFolder: "file:///" - property url saveFolder: "file:///" - property url textureFolder: "file:///" - property url importFolder: "file:///" - property string saveFileTitleAddition: { - if (saveFileUrl != "") - " - " + saveFileUrl.toString().substring(saveFileUrl.toString().lastIndexOf("/") + 1) - else - saveFileUrl.toString() - } - - property int currentHelperPlane: 1 - property alias selectedEntityType: generalPropertyView.entityType - - property bool trackMousePosition: false - property int mousePosY: -1 - property int mousePosX: -1 - - property color textColor: "#ffffff" - property color disabledTextColor: "#a0a1a2" - property color selectionColor: "#43adee" - property color listHighlightColor: "#585a5c" - property color paneBackgroundColor: "#2e2f30" - property color paneColor: "#373839" - property color viewBorderColor: "#000000" - property color itemBackgroundColor: "#46484a" - property color itemColor: "#cccccc" - property color menutItemColor: "#a0a1a2" - property color iconHighlightColor: "#26282a" - property string labelFontFamily: "Open Sans" - property int labelFontWeight: Font.Normal - property int labelFontPixelSize: 12 - property int maximumControlWidth: 200 - property int controlMargin: 4 - - property bool transformViewVisible: true - property bool materialViewVisible: true - property bool meshViewVisible: true - property bool lightViewVisible: true - property bool cameraViewVisible: true - - property real qlcControlHeight: 28 - - property string systemLanguage: editorScene.language - - header: EditorToolbar {} - - FileDialog { - id: loadFileDialog - selectMultiple: false - selectExisting: true - title: qsTr("Load Scene") + editorScene.emptyString - nameFilters: [qsTr("Qt3D Scenes (*.qt3d.qrc)") + editorScene.emptyString] - onAccepted: { - if (editorScene.loadScene(fileUrl)) { - entityTree.selectSceneRoot() - saveFolder = folder - saveFileUrl = fileUrl - } - } - } - - FileDialog { - id: saveFileDialog - selectMultiple: false - selectExisting: false - property bool exiting: false - title: qsTr("Save Scene") + editorScene.emptyString - nameFilters: [qsTr("Qt3D Scenes (*.qt3d.qrc)") + editorScene.emptyString] - onAccepted: { - editorScene.saveScene(fileUrl) - saveFolder = folder - saveFileUrl = fileUrl - if (exiting) - Qt.quit() - } - } - - FileDialog { - id: importEntityDialog - selectMultiple: false - selectExisting: true - title: qsTr("Import Entity") + editorScene.emptyString - nameFilters: [qsTr("All files (*)") + editorScene.emptyString] - onAccepted: { - editorScene.undoHandler.createImportEntityCommand(fileUrl) - importFolder = folder - } - } - - function fileLoad() { - if (!editorScene.undoHandler.isClean()) { - saveUnsavedDialog.newFile = false - saveUnsavedDialog.open() - } else { - loadFileDialog.folder = saveFolder - loadFileDialog.open() - } - } - - function fileSave() { - if (saveFileUrl == "") { - saveFileDialog.folder = saveFolder - saveFileDialog.open() - // No previous autosave file, no need to delete anything - } else { - editorScene.saveScene(saveFileUrl) - editorScene.deleteScene(saveFileUrl, true) - } - } - - function fileSaveAs() { - if (saveFileUrl != "") - editorScene.deleteScene(saveFileUrl, true) - saveFileDialog.folder = saveFolder - saveFileDialog.open() - } - - function undo() { - editorScene.undoHandler.undo() - } - - function redo() { - editorScene.undoHandler.redo() - } - - function fileNew() { - if (!editorScene.undoHandler.isClean()) { - saveUnsavedDialog.newFile = true - saveUnsavedDialog.open() - } else { - editorScene.resetScene() - showNormalYPlane() - saveFileUrl = "" - } - } - - function showNormalXPlane() { - editorScene.helperPlane.enabled = true - editorScene.helperPlaneTransform.rotation = - editorScene.helperPlaneTransform.fromAxisAndAngle(0, 1, 0, 90) - currentHelperPlane = 0 - } - - function showNormalYPlane() { - editorScene.helperPlane.enabled = true - editorScene.helperPlaneTransform.rotation = - editorScene.helperPlaneTransform.fromAxisAndAngle(1, 0, 0, 90) - currentHelperPlane = 1 - } - - function showNormalZPlane() { - editorScene.helperPlane.enabled = true - editorScene.helperPlaneTransform.rotation = - editorScene.helperPlaneTransform.fromAxisAndAngle(0, 0, 1, 90) - currentHelperPlane = 2 - } - - function hideHelperPlane() { - editorScene.helperPlane.enabled = false - currentHelperPlane = 3 - } - - Shortcut { - id: copyShortcut - sequence: StandardKey.Copy - onActivated: { - // Prevent copying multiselection (for now, at least) - if (!editorScene.multiSelection) - mainwindow.copyEntity(selectedEntityName) - } - } - function copyEntity(entityName) { - if (entityName !== editorScene.sceneRootName()) { - // Disable possible previous cut operation - if (editorScene.clipboardOperation === EditorScene.ClipboardCut) { - var index = editorScene.sceneModel.getModelIndexByName( - editorScene.clipboardContent) - var sceneItem = editorScene.sceneModel.editorSceneItemFromIndex(index) - sceneItem.entity().enabled = true - } - trackMousePosition = true - editorScene.clipboardContent = entityName - editorScene.clipboardOperation = EditorScene.ClipboardCopy - // TODO: When to stop reading mouse movements when copy-pasting? - // TODO: When any other operation is done? - } - } - - Shortcut { - id: cutShortcut - sequence: StandardKey.Cut - onActivated: { - // Prevent cutting multiselection (for now, at least) - if (!editorScene.multiSelection) - mainwindow.cutEntity(selectedEntityName, selectedEntity) - } - } - function cutEntity(entityName, entity) { - if (entityName !== editorScene.sceneRootName()) { - trackMousePosition = true - editorScene.clipboardContent = entityName - editorScene.clipboardOperation = EditorScene.ClipboardCut - entity.entity().enabled = false - } - } - - Shortcut { - id: pasteShortcut - sequence: StandardKey.Paste - onActivated: { - mainwindow.pasteEntity() - } - } - function pasteEntity() { - if (editorScene.clipboardContent.length) { - var parentName = "" - if (entityTree.treeviewPasting) { - parentName = selectedEntityName - // Prevent pasting an entity under itself in tree - if (!editorScene.sceneModel.canReparent( - editorScene.sceneModel.editorSceneItemFromIndex( - editorScene.sceneModel.getModelIndexByName( - selectedEntityName)), - editorScene.sceneModel.editorSceneItemFromIndex( - editorScene.sceneModel.getModelIndexByName( - editorScene.clipboardContent)), true)) { - return - } - } - // When pasting to tree, world position is not used, and parent entity name is passed - editorScene.undoHandler.createPasteEntityCommand(editorScene.getWorldPosition( - mousePosX, mousePosY), - parentName) - if (editorScene.clipboardOperation === EditorScene.ClipboardCut) { - trackMousePosition = false - editorScene.clipboardOperation = EditorScene.ClipboardNone - } - } - } - - EditorScene { - id: editorScene - viewport: editorViewport - freeView: true - - onSelectionChanged: { - restoreSelection(selection) - } - - onMultiSelectionListChanged: { - restoreMultiSelection(editorScene.multiSelectionList) - } - - onErrorChanged: { - notification.title = qsTr("Error") + editorScene.emptyString - notification.text = error - notification.open() - } - - onMouseRightButtonReleasedWithoutDragging: { - entityTree.menu.popup() - } - - onClipboardOperationChanged: { - if (clipboardOperation === EditorScene.ClipboardNone) - trackMousePosition = false - } - - function restoreSelection(entity) { - var index = editorScene.sceneModel.getModelIndex(entity) - selectIndex(index) - } - - function restoreMultiSelection(selectionList) { - // Deselect old ones - entityTree.view.selection.clear() - // Dig indexes of all selected entities and pass the selections to entitytree - for (var i = 0; i < selectionList.length; ++i) { - var index = editorScene.sceneModel.getModelIndexByName(multiSelectionList[i]) - entityTree.view.selection.select(index, ItemSelectionModel.Select) - expandTo(index) - } - } - - function selectIndex(index) { - expandTo(index) - entityTree.focusTree() - entityTree.view.selection.setCurrentIndex(index, ItemSelectionModel.ClearAndSelect) - } - - function expandTo(index) { - var target = index - do { - entityTree.view.expand(target) - target = target.parent - } while (target.valid) - } - } - - MessageDialog { - id: notification - icon: StandardIcon.Warning - } - - SettingsDialog { - id: settingsDialog - } - - MessageDialog { - id: closingDialog - icon: StandardIcon.Warning - standardButtons: StandardButton.Yes | StandardButton.No | StandardButton.Cancel - title: qsTr("Exit Qt 3D Scene Editor") + editorScene.emptyString - text: qsTr("There are unsaved changes.\nSave changes before exiting?") - + editorScene.emptyString - - onYes: { - if (saveFileUrl == "") { - saveFileDialog.exiting = true - saveFileDialog.open() - // No previous autosave file, no need to delete anything - saveFileDialog.exiting = false - } else { - editorScene.saveScene(saveFileUrl) - editorScene.deleteScene(saveFileUrl, true) - Qt.quit() - } - } - - onNo: { - Qt.quit() - } - - // Cancel doesn't need to do anything - } - - MessageDialog { - id: saveUnsavedDialog - property bool newFile: false - icon: StandardIcon.Warning - standardButtons: StandardButton.Yes | StandardButton.No | StandardButton.Cancel - title: qsTr("Save changes?") + editorScene.emptyString - text: qsTr("There are unsaved changes.\nSave changes?") - + editorScene.emptyString - - onYes: { - if (saveFileUrl == "") { - saveFileDialog.folder = saveFolder - saveFileDialog.open() - // No previous autosave file, no need to delete anything - } else { - editorScene.saveScene(saveFileUrl) - editorScene.deleteScene(saveFileUrl, true) - } - } - - onNo: { - if (newFile) { - editorScene.resetScene() - showNormalYPlane() - saveFileUrl = "" - } else { - loadFileDialog.folder = saveFolder - loadFileDialog.open() - } - } - - // Cancel doesn't need to do anything - } - - SplitView { - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: parent.left - orientation: Qt.Horizontal - width: parent.width - propertyPane.visibleWidth - - // Entity library - EntityLibrary { - id: entityLibrary - z: 4 - Layout.minimumWidth: 100 - Layout.maximumWidth: mainwindow.width - 10 - onCreateNewEntity: { - entityTree.selectSceneRoot() - entityTree.addNewEntity(entityType, xPos, yPos) - } - } - - Item { - Layout.fillWidth: true - Layout.minimumWidth: 100 - - EditorViewport { - id: editorViewport - anchors.fill: parent - scene: editorScene - - MouseArea { - id: viewportMouseArea - anchors.fill: parent - onPressed: { - entityTree.focusTree() - mouse.accepted = false - } - onEntered: entityTree.treeviewPasting = false - hoverEnabled: trackMousePosition - onMouseYChanged: mousePosY = mouseY - onMouseXChanged: mousePosX = mouseX - } - - DropArea { - anchors.fill: parent - keys: [ "insertEntity" ] - onContainsDragChanged: { - dragEntityItem.visible = !containsDrag - } - } - DragHandle { - // This is the translate handle at the center of selection box - handleType: EditorScene.DragTranslate - baseZ: 3 // Make sure translate handle is on top of scale handles - color: "#c22555" - radius: height / 2 - handleIndex: 0 - } - DragHandle { - // This is the group/mesh center indicator handle - handleType: EditorScene.DragTranslate - baseZ: 3 // Make sure center handle is on top of scale handles - color: "blue" - radius: height / 2 - handleIndex: 1 - } - DragHandle { - handleType: EditorScene.DragRotate - baseZ: 3 // Make sure rotate handle is on top of scale handles - Image { - anchors.fill: parent - source: "images/rotate_handle.png" - } - color: "transparent" - } - // Each corner will have a separate drag handle - DragHandle { - handleType: EditorScene.DragScale - handleIndex: 0 - } - DragHandle { - handleType: EditorScene.DragScale - handleIndex: 1 - } - DragHandle { - handleType: EditorScene.DragScale - handleIndex: 2 - } - DragHandle { - handleType: EditorScene.DragScale - handleIndex: 3 - } - DragHandle { - handleType: EditorScene.DragScale - handleIndex: 4 - } - DragHandle { - handleType: EditorScene.DragScale - handleIndex: 5 - } - DragHandle { - handleType: EditorScene.DragScale - handleIndex: 6 - } - DragHandle { - handleType: EditorScene.DragScale - handleIndex: 7 - } - - // Debug handle for visualizing world positions, uncomment to use. - // You can show debug handles with EditorScene::showDebugHandle(). -// DragHandle { -// handleType: EditorScene.DragDebug -// color: "green" -// baseZ: 4 -// } - } - } - } - - SplitView { - id: propertyPane - orientation: Qt.Vertical - anchors.top: parent.top - anchors.bottom: parent.bottom - width: mainwindow.width / 4.5 - x: mainwindow.width - visibleWidth - - property int visibleWidth: width - - // Entity list - EntityTree { - id: entityTree - } - - GeneralPropertyView { - id: generalPropertyView - entityName: selectedEntityName - entityType: editorScene.sceneModel.editorSceneItemFromIndex(entityTree.view.selection.currentIndex).itemType() - propertiesButtonVisible: { - (entityTree.view.selection.currentIndex - !== editorScene.sceneModel.sceneEntityIndex()) - ? true : false - } - } - - // Property (transform, material, etc.) list - ListView { - id: componentPropertiesView - Layout.fillHeight: true - delegate: ComponentPropertiesDelegate {} - flickableDirection: Flickable.VerticalFlick - boundsBehavior: Flickable.StopAtBounds - clip: true - visible: generalPropertyView.viewTitleVisible - } - } - - onWidthChanged: { - var maximumWidth = mainwindow.width - entityLibrary.width - 10 - if (propertyPane.visibleWidth > maximumWidth) { - propertyPane.visibleWidth = maximumWidth - propertyPane.width = propertyPane.visibleWidth - } else if (propertyPane.visibleWidth > resizeRectangle.paneMinimumWidth) { - propertyPane.width = propertyPane.visibleWidth - } - propertyPane.x = mainwindow.width - propertyPane.visibleWidth - } - - Rectangle { - id: resizeRectangle - width: 2 - height: parent.height - anchors.right: propertyPane.left - color: mainwindow.viewBorderColor - - property int paneMinimumWidth: 250 - property int paneMaximumWidth: mainwindow.width - entityLibrary.width - 10 - - MouseArea { - anchors.fill: parent - hoverEnabled: true - - drag { - target: parent; - axis: Drag.XAxis - } - - onEntered: { - cursorShape = Qt.SplitHCursor - } - - onExited: { - cursorShape = Qt.ArrowCursor - } - - onMouseXChanged: { - if (drag.active) { - var newPaneWidth = propertyPane.width - mouseX - if (propertyPane.visibleWidth < resizeRectangle.paneMinimumWidth - || newPaneWidth < resizeRectangle.paneMinimumWidth) { - var newXPos = propertyPane.x + mouseX - if (newXPos < mainwindow.width) { - propertyPane.visibleWidth = mainwindow.width - newXPos - propertyPane.x = newXPos - } - } - else if (newPaneWidth > resizeRectangle.paneMinimumWidth - && newPaneWidth < resizeRectangle.paneMaximumWidth) { - propertyPane.x = mainwindow.width - newPaneWidth - propertyPane.width = newPaneWidth - propertyPane.visibleWidth = propertyPane.width - } - } - } - } - } - - Timer { - id: autoSaveTimer - running: false - interval: 600000 // 10 minutes - repeat: true - onTriggered: { - editorScene.saveScene(saveFileUrl, true) - } - } - - function resetCameraToDefault() { - editorScene.freeView = true - editorScene.resetFreeViewCamera() - } - - function checkUnsavedChanges() { - if (!editorScene.undoHandler.isClean()) { - closingDialog.open() - return false - } - return true - } - - onClosing: { - close.accepted = checkUnsavedChanges() - } - - Component.onCompleted: { - Qt.application.organization = "The Qt Company" - Qt.application.domain = "qt.io" - Qt.application.name = "Qt 3D Scene Editor" - // Redraw everything to get rid of artifacts - showMaximized() - show() - visible = true - } -} diff --git a/editorlib/qml/transforms/SRTTransformDelegate.qml b/editorlib/qml/transforms/SRTTransformDelegate.qml index 6f4386a..ddad8f0 100644 --- a/editorlib/qml/transforms/SRTTransformDelegate.qml +++ b/editorlib/qml/transforms/SRTTransformDelegate.qml @@ -40,7 +40,7 @@ TransformDelegate { component: transformComponentData componentType: thisDelegate.componentType lockedField: enabledField - visible: selectedEntityType !== EditorSceneItem.Light + visible: editorContent.selectedEntityType !== EditorSceneItem.Light tooltip: qsTr("The scale of the object\non the %1 axis.") + editorScene.emptyString tooltipArgs: ["X", "Y", "Z"] @@ -54,7 +54,7 @@ TransformDelegate { minimum: 0 maximum: 359 lockedField: enabledField - visible: selectedEntityType !== EditorSceneItem.Light + visible: editorContent.selectedEntityType !== EditorSceneItem.Light tooltip: qsTr("Angle of the rotation. Is applied\nto axes that have non-zero value.") + editorScene.emptyString } diff --git a/editorlib/src/qt3dsceneeditor.cpp b/editorlib/src/qt3dsceneeditor.cpp index 358718a..b8bcfea 100644 --- a/editorlib/src/qt3dsceneeditor.cpp +++ b/editorlib/src/qt3dsceneeditor.cpp @@ -37,17 +37,25 @@ #include "editorsceneitemmeshcomponentsmodel.h" #include "editorsceneitemlightcomponentsmodel.h" +namespace Qt3DSceneEditorLib { + QT3D_SCENE_EDITOR_EXPORT void register3DSceneEditorQML() { - qmlRegisterType<EditorScene>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorScene"); - qmlRegisterType<EditorViewportItem>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorViewport"); - qmlRegisterUncreatableType<EditorSceneItemModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemModel", "Created by EditorScene"); - qmlRegisterUncreatableType<EditorSceneItem>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItem", "Created by EditorScene"); - qmlRegisterUncreatableType<EditorSceneItemComponentsModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemComponentsModel", "Created by EditorSceneItem"); - qmlRegisterUncreatableType<EditorSceneItemTransformComponentsModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemTransformComponentsModel", "Created by EditorSceneItemComponentsModel"); - qmlRegisterUncreatableType<EditorSceneItemMaterialComponentsModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemMaterialComponentsModel", "Created by EditorSceneItemComponentsModel"); - qmlRegisterUncreatableType<EditorSceneItemMeshComponentsModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemMeshComponentsModel", "Created by EditorSceneItemComponentsModel"); - qmlRegisterUncreatableType<EditorSceneItemLightComponentsModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemLightComponentsModel", "Created by EditorSceneItemComponentsModel"); - qmlRegisterUncreatableType<UndoHandler>("com.theqtcompany.SceneEditor3D", 1, 0, "UndoHandler", "Created by EditorScene"); - qmlRegisterUncreatableType<EditorUtils>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorUtils", "Created by EditorScene"); + static bool registered = false; + if (!registered) { + qmlRegisterType<EditorScene>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorScene"); + qmlRegisterType<EditorViewportItem>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorViewport"); + qmlRegisterUncreatableType<EditorSceneItemModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemModel", "Created by EditorScene"); + qmlRegisterUncreatableType<EditorSceneItem>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItem", "Created by EditorScene"); + qmlRegisterUncreatableType<EditorSceneItemComponentsModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemComponentsModel", "Created by EditorSceneItem"); + qmlRegisterUncreatableType<EditorSceneItemTransformComponentsModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemTransformComponentsModel", "Created by EditorSceneItemComponentsModel"); + qmlRegisterUncreatableType<EditorSceneItemMaterialComponentsModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemMaterialComponentsModel", "Created by EditorSceneItemComponentsModel"); + qmlRegisterUncreatableType<EditorSceneItemMeshComponentsModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemMeshComponentsModel", "Created by EditorSceneItemComponentsModel"); + qmlRegisterUncreatableType<EditorSceneItemLightComponentsModel>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorSceneItemLightComponentsModel", "Created by EditorSceneItemComponentsModel"); + qmlRegisterUncreatableType<UndoHandler>("com.theqtcompany.SceneEditor3D", 1, 0, "UndoHandler", "Created by EditorScene"); + qmlRegisterUncreatableType<EditorUtils>("com.theqtcompany.SceneEditor3D", 1, 0, "EditorUtils", "Created by EditorScene"); + registered = true; + } +} + } diff --git a/editorlib/src/qt3dsceneeditor.h b/editorlib/src/qt3dsceneeditor.h index 24a8940..e4d2aff 100644 --- a/editorlib/src/qt3dsceneeditor.h +++ b/editorlib/src/qt3dsceneeditor.h @@ -37,6 +37,10 @@ # define QT3D_SCENE_EDITOR_EXPORT Q_DECL_IMPORT #endif +namespace Qt3DSceneEditorLib { + QT3D_SCENE_EDITOR_EXPORT void register3DSceneEditorQML(); +} + #endif // QT3DSCENEEDITOR_H diff --git a/standalone/main.cpp b/standalone/main.cpp index d76fe64..8d7bb7e 100644 --- a/standalone/main.cpp +++ b/standalone/main.cpp @@ -37,10 +37,10 @@ int main(int argc, char *argv[]) app.setOrganizationDomain("qt.io"); app.setApplicationName("Qt 3D Scene Editor"); - register3DSceneEditorQML(); + Qt3DSceneEditorLib::register3DSceneEditorQML(); QQmlApplicationEngine engine; - engine.load(QUrl(QStringLiteral("qrc:/qt3deditorlib/main.qml"))); + engine.load(QUrl(QStringLiteral("qrc:/qt3deditorlib/StandaloneMain.qml"))); return app.exec(); } |