summaryrefslogtreecommitdiffstats
path: root/src/Authoring/Studio/_Win
diff options
context:
space:
mode:
Diffstat (limited to 'src/Authoring/Studio/_Win')
-rw-r--r--src/Authoring/Studio/_Win/Application/AboutDlg.cpp314
-rw-r--r--src/Authoring/Studio/_Win/Application/AboutDlg.h95
-rw-r--r--src/Authoring/Studio/_Win/Application/AboutDlg.ui180
-rw-r--r--src/Authoring/Studio/_Win/Application/BaseLink.cpp252
-rw-r--r--src/Authoring/Studio/_Win/Application/BaseLink.h76
-rw-r--r--src/Authoring/Studio/_Win/Application/MsgRouter.cpp131
-rw-r--r--src/Authoring/Studio/_Win/Application/StudioApp.cpp1835
-rw-r--r--src/Authoring/Studio/_Win/Application/StudioApp.h255
-rw-r--r--src/Authoring/Studio/_Win/Application/StudioColors.h137
-rw-r--r--src/Authoring/Studio/_Win/Application/SubPresentationsDlg.cpp172
-rw-r--r--src/Authoring/Studio/_Win/Application/SubPresentationsDlg.h82
-rw-r--r--src/Authoring/Studio/_Win/Application/SubPresentationsDlg.ui152
-rw-r--r--src/Authoring/Studio/_Win/Application/TextLink.cpp100
-rw-r--r--src/Authoring/Studio/_Win/Application/TextLink.h73
-rw-r--r--src/Authoring/Studio/_Win/Application/WebLink.cpp440
-rw-r--r--src/Authoring/Studio/_Win/Application/WebLink.h100
-rw-r--r--src/Authoring/Studio/_Win/Controls/AppFonts.cpp89
-rw-r--r--src/Authoring/Studio/_Win/Controls/AppFonts.h61
-rw-r--r--src/Authoring/Studio/_Win/Controls/BufferedRenderer.cpp214
-rw-r--r--src/Authoring/Studio/_Win/Controls/BufferedRenderer.h60
-rw-r--r--src/Authoring/Studio/_Win/Controls/MFCEditControl.cpp278
-rw-r--r--src/Authoring/Studio/_Win/Controls/MFCEditControl.h85
-rw-r--r--src/Authoring/Studio/_Win/Controls/OffscreenRenderer.cpp66
-rw-r--r--src/Authoring/Studio/_Win/Controls/OffscreenRenderer.h61
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformEditControl.cpp144
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformEditControl.h85
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformStaticControl.cpp68
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformStaticControl.h66
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformWindowControl.cpp96
-rw-r--r--src/Authoring/Studio/_Win/Controls/PlatformWindowControl.h69
-rw-r--r--src/Authoring/Studio/_Win/Controls/WinRenderer.cpp525
-rw-r--r--src/Authoring/Studio/_Win/Controls/WinRenderer.h130
-rw-r--r--src/Authoring/Studio/_Win/Controls/WndControl.cpp1006
-rw-r--r--src/Authoring/Studio/_Win/Controls/WndControl.h148
-rw-r--r--src/Authoring/Studio/_Win/DragNDrop/DropProxy.cpp341
-rw-r--r--src/Authoring/Studio/_Win/DragNDrop/DropProxy.h82
-rw-r--r--src/Authoring/Studio/_Win/DragNDrop/WinDnd.cpp119
-rw-r--r--src/Authoring/Studio/_Win/DragNDrop/WinDnd.h64
-rw-r--r--src/Authoring/Studio/_Win/Include/StudioPrefixWin32.h39
-rw-r--r--src/Authoring/Studio/_Win/Palettes/PaletteManager.cpp902
-rw-r--r--src/Authoring/Studio/_Win/Palettes/PaletteManager.h153
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.cpp127
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.h58
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.cpp178
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.h80
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.cpp94
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.h54
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Splash/SplashView.cpp92
-rw-r--r--src/Authoring/Studio/_Win/Palettes/Splash/SplashView.h71
-rw-r--r--src/Authoring/Studio/_Win/Studio/stdafx.cpp33
-rw-r--r--src/Authoring/Studio/_Win/Studio/stdafx.h221
-rw-r--r--src/Authoring/Studio/_Win/UI/ContextMenu.cpp292
-rw-r--r--src/Authoring/Studio/_Win/UI/ControlButton.cpp471
-rw-r--r--src/Authoring/Studio/_Win/UI/ControlButton.h119
-rw-r--r--src/Authoring/Studio/_Win/UI/CrashDlg.cpp212
-rw-r--r--src/Authoring/Studio/_Win/UI/CrashDlg.h96
-rw-r--r--src/Authoring/Studio/_Win/UI/EditCameraBar.cpp226
-rw-r--r--src/Authoring/Studio/_Win/UI/EditCameraBar.h99
-rw-r--r--src/Authoring/Studio/_Win/UI/EditorPane.cpp90
-rw-r--r--src/Authoring/Studio/_Win/UI/EditorPane.h65
-rw-r--r--src/Authoring/Studio/_Win/UI/FileDialogEX.cpp451
-rw-r--r--src/Authoring/Studio/_Win/UI/FileDialogEX.h111
-rw-r--r--src/Authoring/Studio/_Win/UI/GLVersionDlg.cpp91
-rw-r--r--src/Authoring/Studio/_Win/UI/GLVersionDlg.h75
-rw-r--r--src/Authoring/Studio/_Win/UI/InterpolationDlg.cpp78
-rw-r--r--src/Authoring/Studio/_Win/UI/InterpolationDlg.h66
-rw-r--r--src/Authoring/Studio/_Win/UI/InterpolationDlg.ui305
-rw-r--r--src/Authoring/Studio/_Win/UI/MemoryDC.cpp258
-rw-r--r--src/Authoring/Studio/_Win/UI/MemoryDC.h91
-rw-r--r--src/Authoring/Studio/_Win/UI/MenuEdit.cpp169
-rw-r--r--src/Authoring/Studio/_Win/UI/MenuEdit.h72
-rw-r--r--src/Authoring/Studio/_Win/UI/MenuItem.cpp58
-rw-r--r--src/Authoring/Studio/_Win/UI/MenuItem.h60
-rw-r--r--src/Authoring/Studio/_Win/UI/NumericEdit.cpp347
-rw-r--r--src/Authoring/Studio/_Win/UI/NumericEdit.h101
-rw-r--r--src/Authoring/Studio/_Win/UI/PlayerContainerWnd.cpp510
-rw-r--r--src/Authoring/Studio/_Win/UI/PlayerContainerWnd.h106
-rw-r--r--src/Authoring/Studio/_Win/UI/PlayerWnd.cpp278
-rw-r--r--src/Authoring/Studio/_Win/UI/PlayerWnd.h99
-rw-r--r--src/Authoring/Studio/_Win/UI/PopupWnd.cpp248
-rw-r--r--src/Authoring/Studio/_Win/UI/PopupWnd.h104
-rw-r--r--src/Authoring/Studio/_Win/UI/PreviewOutputDlg.cpp366
-rw-r--r--src/Authoring/Studio/_Win/UI/PreviewOutputDlg.h92
-rw-r--r--src/Authoring/Studio/_Win/UI/RecentItems.cpp145
-rw-r--r--src/Authoring/Studio/_Win/UI/RecentItems.h88
-rw-r--r--src/Authoring/Studio/_Win/UI/ReportDlg.cpp198
-rw-r--r--src/Authoring/Studio/_Win/UI/ReportDlg.h100
-rw-r--r--src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.cpp66
-rw-r--r--src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.h57
-rw-r--r--src/Authoring/Studio/_Win/UI/SceneView.cpp861
-rw-r--r--src/Authoring/Studio/_Win/UI/SceneView.h174
-rw-r--r--src/Authoring/Studio/_Win/UI/StartupDlg.cpp174
-rw-r--r--src/Authoring/Studio/_Win/UI/StartupDlg.h114
-rw-r--r--src/Authoring/Studio/_Win/UI/StartupDlg.ui171
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.cpp590
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.h121
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.ui183
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioPaletteBar.cpp260
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioPaletteBar.h88
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.cpp155
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.h105
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.ui102
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.cpp385
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.h103
-rw-r--r--src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.ui125
-rw-r--r--src/Authoring/Studio/_Win/UI/TimeEditDlg.cpp524
-rw-r--r--src/Authoring/Studio/_Win/UI/TimeEditDlg.h190
-rw-r--r--src/Authoring/Studio/_Win/UI/timeeditdlg.ui364
-rw-r--r--src/Authoring/Studio/_Win/Utils/MouseCursor.cpp199
-rw-r--r--src/Authoring/Studio/_Win/Utils/WinUtils.cpp600
-rw-r--r--src/Authoring/Studio/_Win/Utils/WinUtils.h65
-rw-r--r--src/Authoring/Studio/_Win/Workspace/Dialogs.cpp1332
-rw-r--r--src/Authoring/Studio/_Win/Workspace/Views.cpp195
113 files changed, 23993 insertions, 0 deletions
diff --git a/src/Authoring/Studio/_Win/Application/AboutDlg.cpp b/src/Authoring/Studio/_Win/Application/AboutDlg.cpp
new file mode 100644
index 00000000..533a5601
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/AboutDlg.cpp
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "qtAuthoring-config.h"
+#include "StudioDefs.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "AboutDlg.h"
+#include "ui_AboutDlg.h"
+#include "ProductInfo.h"
+#include "HotKeys.h"
+#include "Preferences.h"
+#include "StudioPreferences.h"
+
+#include <QMouseEvent>
+#include <QPainter>
+#include <QTimer>
+
+//==============================================================================
+// Constants
+//==============================================================================
+const int TIMER_RESIZEABOUT = 6;
+const int TIMER_FADEOUT = 7;
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+CAboutDlg::CAboutDlg(QWidget* parent)
+ : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint)
+ , m_ScrollingCreditsFlag(false)
+ , m_ui(new Ui::AboutDlg)
+{
+ m_ui->setupUi(this);
+ m_IconRect = m_ui->icon->pixmap()->rect();
+ setFixedSize(size());
+
+ m_Font = QFont(CStudioPreferences::GetFontFaceName());
+ m_Font.setPointSizeF(7.8);
+ m_Font = QFont(CStudioPreferences::GetFontFaceName());
+ m_Font.setPointSizeF(8.8);
+
+ m_Color_Background = CStudioPreferences::GetDarkBaseColor();
+ m_Color_Text = CStudioPreferences::GetNormalColor();
+
+ OnInitDialog();
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+CAboutDlg::~CAboutDlg()
+{
+}
+
+//==============================================================================
+/**
+ * Handles the painting of the icon in the About Box.
+ * All additional painting (text, etc) occurs by default by MFC.
+ */
+//==============================================================================
+void CAboutDlg::paintEvent(QPaintEvent* event)
+{
+ Q_UNUSED(event);
+ if (!m_ScrollingCreditsFlag) {
+ DrawFadeRect();
+ }
+}
+
+//==============================================================================
+/**
+ * Completes the construction of the About Box.
+ * Stores the product version in the member variable associated with the static
+ * text box in the dialog template. This version information comes from the
+ * VersionNumber.h file in $/Studio/Build.
+ * @return Returns TRUE always.
+ */
+void CAboutDlg::OnInitDialog()
+{
+ // Set the Studio version
+ m_ProductVersionStr.Format(
+ ::LoadResourceString(IDS_UIC_STUDIO_VERSION),
+ static_cast<const wchar_t *>(CStudioPreferences::GetVersionString()));
+
+ // Set the copyright string
+ m_CopyrightStr.Format(::LoadResourceString(IDS_ABOUT_COPYRIGHT),
+ static_cast<const wchar_t *>(Q3DStudio::CString(STUDIO_COPYRIGHT_YEAR)));
+
+ // Set the credit strings
+ m_Credit1Str.Format(::LoadResourceString(IDS_ABOUT_PAINTLIB_CREDIT));
+#ifdef QT_3DSTUDIO_FBX
+ m_Credit2Str.Format(::LoadResourceString(IDS_ABOUT_FBX_CREDIT));
+#endif
+
+#ifdef STUDIOSTORYNUM
+ m_ProductVersionStr += " (Story #";
+ m_ProductVersionStr += STUDIOSTORYNUM;
+ m_ProductVersionStr += ")";
+#endif
+
+#ifdef BETA
+ // Add "beta" to the Studio version if necessary
+ m_ProductVersionStr += " BETA";
+#endif
+
+ // Add link to Web site
+ Q3DStudio::CString theURL(::LoadResourceString(IDS_HELP_VISIT_QT));
+
+ m_ui->m_WebSite->setText(QString("<a href=\"%1\">%2</a>").arg(theURL.toQString(), theURL.toQString()));
+ m_ui->m_WebSite->setToolTip(::LoadResourceString(IDS_WEBSITELINK).toQString());
+ m_ui->m_WebSite->setOpenExternalLinks(true);
+
+ // Add link to support email address
+ Q3DStudio::CString theEmail;
+ Q3DStudio::CString theEmailSansProtocol;
+
+ theEmail = ::LoadResourceString(IDS_SUPPORTEMAIL);
+ theEmailSansProtocol = "support@qt.io";
+
+ m_ui->m_Email->setText(QString("<a href=\"%1\">%2</a>").arg(theEmail.toQString(), theEmailSansProtocol.toQString()));
+ m_ui->m_Email->setToolTip(::LoadResourceString(IDS_SUPPORTEMAIL_TEXT).toQString());
+ m_ui->m_Email->setOpenExternalLinks(true);
+
+ // Set the fonts
+ m_ui->m_Copyright->setFont(m_Font);
+ m_ui->m_Credit1->setFont(m_Font);
+ m_ui->m_Credit2->setFont(m_Font);
+ m_ui->m_WebSiteLabel->setFont(m_Font);
+ m_ui->m_WebSite->setFont(m_Font);
+ m_ui->m_EmailLabel->setFont(m_Font);
+ m_ui->m_Email->setFont(m_Font);
+
+ // Make the font bold for version numbers
+ m_ui->m_ProductVersion->setFont(m_BoldFont);
+
+ // Create brush for background color
+ m_Brush = QBrush(m_Color_Background);
+
+ m_ui->m_ProductVersion->setText(m_ProductVersionStr.toQString());
+ m_ui->m_Copyright->setText(m_CopyrightStr.toQString());
+ m_ui->m_Credit1->setText(m_Credit1Str.toQString());
+ m_ui->m_Credit2->setText(m_Credit2Str.toQString());
+
+ // Hide the email link until we have a valid one.
+ m_ui->m_EmailLabel->setVisible(false);
+ m_ui->m_Email->setVisible(false);
+}
+
+//==============================================================================
+/**
+ * Handles the WM_LBUTTONDBLCLK message
+ * Check to see if the mouse is within the Qt logo and the control key is pressed.
+ * If so, begin the transition to show the detailed credits.
+ */
+void CAboutDlg::mouseDoubleClickEvent(QMouseEvent* event)
+{
+ // If the mouse's left button is double-clicked in the Qt logo while the control key is
+ // pressed...
+ if (m_IconRect.contains(event->pos())) {
+ // if ( CHotKeys::IsKeyDown( VK_CONTROL ) )
+ //{
+ // Start the transition to display the scrolling credits
+ // Crashing... this->BeginCreditsTransition();
+ //}
+ }
+
+ QDialog::mouseDoubleClickEvent(event);
+}
+
+//==============================================================================
+/**
+ * BeginCreditsTransition: Begin the transition from the About box to the scrolling credits.
+ */
+void CAboutDlg::BeginCreditsTransition()
+{
+ m_ScrollingCreditsFlag = TRUE;
+
+ // Hide all controls
+ for (QWidget* w : findChildren<QWidget*>())
+ w->setVisible(false);
+
+ // Invalidate the window
+ update();
+
+ // Set the resizing timer
+ QTimer::singleShot(50, this, &CAboutDlg::ResizeAbout);
+}
+
+//==============================================================================
+/**
+ * Resize the about box height until the Client area is square.
+ */
+void CAboutDlg::ResizeAbout()
+{
+ bool retriggerResizeAbout = true;
+
+ QRect theClientRect = rect();
+ bool theRightSize = false;
+
+ // this is just a sizing stuff to show some transition on size
+ if (theClientRect.height() < theClientRect.width()) {
+ theClientRect.setBottom(theClientRect.bottom() + 5);
+ if (theClientRect.bottom() >= theClientRect.width()) {
+ theRightSize = true;
+ theClientRect.setBottom(theClientRect.width());
+ retriggerResizeAbout = false;
+ }
+ } else {
+ theClientRect.setRight(theClientRect.right() + 5);
+ if (theClientRect.right() >= theClientRect.height()) {
+ theRightSize = true;
+ theClientRect.setRight(theClientRect.height());
+ retriggerResizeAbout = false;
+ }
+ }
+
+ if (parentWidget())
+ theClientRect.moveCenter(parentWidget()->geometry().center());
+ else
+ theClientRect.moveTopLeft(geometry().topLeft());
+
+ setGeometry(theClientRect);
+
+ if (theRightSize) {
+ QColor the3DColor;
+ short theColorValue;
+
+ m_CreditsRect = rect().adjusted(3, 3, -3, -3);
+
+ the3DColor = palette().color(QPalette::Base);
+ theColorValue =
+ (short)((the3DColor.red() + the3DColor.green() + the3DColor.blue()) / 3);
+
+ m_ColorFade = RGB(theColorValue, theColorValue, theColorValue);
+
+ QTimer::singleShot(50, this, &CAboutDlg::FadeOut);
+ }
+
+ if (retriggerResizeAbout) {
+ QTimer::singleShot(50, this, &CAboutDlg::ResizeAbout);
+ }
+}
+
+//==============================================================================
+/**
+ * Fade out a rectangle in the client area, from the background 3D color to black.
+ */
+void CAboutDlg::FadeOut()
+{
+ update();
+
+ // Continue fading to black
+ if (m_ColorFade != Qt::black) {
+ short theColorValue;
+
+ theColorValue = (short)(m_ColorFade.red() - 10);
+
+ if (theColorValue < 0)
+ theColorValue = 0;
+
+ m_ColorFade = qRgb(theColorValue, theColorValue, theColorValue);
+ QTimer::singleShot(50, this, &CAboutDlg::FadeOut);
+ }
+}
+
+//==============================================================================
+/**
+ * DrawFadeRect: Draw the faded rectangle as we transition to the scrolling credits.
+ */
+void CAboutDlg::DrawFadeRect()
+{
+ QPainter painter(this);
+ painter.fillRect(m_CreditsRect, m_ColorFade);
+}
+
+void CAboutDlg::OnStnClickedAboutboxProdver()
+{
+ // TODO: Add your control notification handler code here
+}
diff --git a/src/Authoring/Studio/_Win/Application/AboutDlg.h b/src/Authoring/Studio/_Win/Application/AboutDlg.h
new file mode 100644
index 00000000..244e7192
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/AboutDlg.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_ABOUT_DLG_H
+#define INCLUDED_ABOUT_DLG_H 1
+
+#pragma once
+
+#include <QDialog>
+
+#include "UICString.h"
+
+#ifdef QT_NAMESPACE
+using namespace QT_NAMESPACE;
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class AboutDlg;
+}
+QT_END_NAMESPACE
+
+class CAboutDlg : public QDialog
+{
+ Q_OBJECT
+public:
+ CAboutDlg(QWidget* parent = nullptr);
+ ~CAboutDlg();
+
+ // Implementation
+protected:
+ bool m_ScrollingCreditsFlag = false; // TRUE if credits are being scrolled
+ QRect m_IconRect; // bounding rectangle to display the about image
+ QRect m_CreditsRect; // bounding rectangle for the scrolling credits
+ QColor m_ColorFade; // fade-out color to fade to the credits window
+ QFont m_Font; // Font for text
+ QFont m_BoldFont; // Font for Studio/Client version number
+
+ QColor m_Color_Background;
+ QColor m_Color_Text;
+ QBrush m_Brush;
+
+ void BeginCreditsTransition();
+
+ void DrawFadeRect();
+
+ void FadeOut();
+
+ void ResizeAbout();
+
+ //{{AFX_MSG(CAboutDlg)
+ void paintEvent(QPaintEvent* event) override;
+ void OnInitDialog();
+
+ void mouseDoubleClickEvent(QMouseEvent* event) override;
+
+ Q3DStudio::CString m_ProductVersionStr;
+ Q3DStudio::CString m_CopyrightStr;
+ Q3DStudio::CString m_Credit1Str;
+ Q3DStudio::CString m_Credit2Str;
+
+public:
+ void OnStnClickedAboutboxProdver();
+
+private:
+ QScopedPointer<Ui::AboutDlg> m_ui;
+};
+
+#endif // INCLUDED_ABOUT_DLG_H
diff --git a/src/Authoring/Studio/_Win/Application/AboutDlg.ui b/src/Authoring/Studio/_Win/Application/AboutDlg.ui
new file mode 100644
index 00000000..a5fe3433
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/AboutDlg.ui
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AboutDlg</class>
+ <widget class="QDialog" name="AboutDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>502</width>
+ <height>483</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>About Qt 3D Studio</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="icon">
+ <property name="pixmap">
+ <pixmap resource="../../MainFrm.qrc">:/res/About Icon.bmp</pixmap>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="widget" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="Line" name="m_Line1">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_ProductVersion">
+ <property name="text">
+ <string>&lt;studio version goes here&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_Copyright">
+ <property name="text">
+ <string>&lt;Copyright goes here&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_Credit1">
+ <property name="text">
+ <string>&lt;Credit 1 goes here&gt;</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_Credit2">
+ <property name="text">
+ <string>&lt;Credit 2 goes here&gt;</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="m_Line2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_WebSiteLabel">
+ <property name="text">
+ <string>Web site:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_WebSite">
+ <property name="text">
+ <string>&lt;Link to support site here&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_EmailLabel">
+ <property name="text">
+ <string>Support email:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="m_Email">
+ <property name="text">
+ <string>&lt;Link to support email here&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../MainFrm.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>AboutDlg</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>AboutDlg</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/Authoring/Studio/_Win/Application/BaseLink.cpp b/src/Authoring/Studio/_Win/Application/BaseLink.cpp
new file mode 100644
index 00000000..5e7b4775
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/BaseLink.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+#ifdef _DEBUG
+//#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "BaseLink.h"
+#include "Resource.h"
+#include "StudioColors.h"
+
+// The IDC_HAND should be defined in WinUser.h if the WINVER is 0x5000 or greater
+#ifndef IDC_HAND
+#define IDC_HAND MAKEINTRESOURCE(32649)
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CBaseLink class
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CBaseLink::CBaseLink()
+{
+ m_bCapture = FALSE;
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CBaseLink::~CBaseLink()
+{
+}
+
+//==============================================================================
+// Message Map
+//==============================================================================
+
+BEGIN_MESSAGE_MAP(CBaseLink, CWnd)
+//{{AFX_MSG_MAP(CBaseLink)
+ON_WM_PAINT()
+ON_WM_SETCURSOR()
+ON_WM_MOUSEMOVE()
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * ShowTextLink: Shows the text link.
+ *
+ * @param None
+ */
+//==============================================================================
+void CBaseLink::ShowTextLink(COLORREF inTextColor, COLORREF inBackColor, UINT inTextFormat,
+ bool inUnderlineText)
+{
+ if (IsWindow(m_hWnd)) {
+ CRect theRect;
+ CFont *theFont;
+ CFont *theOldFont = nullptr;
+ CDC *theDC;
+ CDC theMemDC;
+ CString theTextBuffer;
+
+ // Set up the link font.
+ theFont = GetFont();
+ if (theFont != nullptr) {
+ LOGFONT theLogFont;
+
+ theFont->GetLogFont(&theLogFont);
+
+ // Turn on the underline style...
+ if (inUnderlineText)
+ theLogFont.lfUnderline = TRUE;
+ else
+ theLogFont.lfUnderline = FALSE;
+
+ theFont = new CFont();
+
+ if (theFont != nullptr) {
+ theFont->CreateFontIndirect(&theLogFont);
+ }
+ }
+
+ GetClientRect(&theRect);
+ GetWindowText(theTextBuffer);
+
+ theDC = GetDC();
+
+ theDC->SetTextColor(inTextColor);
+ theDC->SetBkColor(inBackColor);
+
+ // Fill the background.
+ theDC->FillSolidRect(&theRect, inBackColor);
+
+ // Set the font and draw the text.
+ if (theFont != nullptr) {
+ theOldFont = (CFont *)theDC->SelectObject(theFont);
+ }
+ theDC->DrawText(theTextBuffer, &theRect, inTextFormat);
+
+ if (theOldFont != nullptr) {
+ theDC->SelectObject(theOldFont);
+ }
+ ReleaseDC(theDC);
+
+ if (theFont != nullptr) {
+ theFont->DeleteObject();
+ delete theFont;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CBaseLink message handlers
+
+//==============================================================================
+/**
+ * OnPaint - Handler for the WM_PAINT message
+ *
+ * Draw the control.
+ *
+ * @param None
+ */
+//==============================================================================
+void CBaseLink::OnPaint()
+{
+ CPaintDC dc(this); // device context for painting
+
+ if (IsWindowEnabled())
+ this->ShowLink();
+}
+
+//==============================================================================
+/**
+ * OnSetCursor
+ *
+ * Handle the WM_SETCURSOR message.
+ *
+ * @param inWnd Pointer to the parent CWnd object.
+ * @param inHitTest Specifies the hit-test area code. The hit test determines the
+ *cursor�s location.
+ * @param inMessage Specifies the mouse message number.
+ */
+//==============================================================================
+BOOL CBaseLink::OnSetCursor(CWnd *inWnd, UINT inHitTest, UINT inMessage)
+{
+ UNREFERENCED_PARAMETER(inWnd);
+ UNREFERENCED_PARAMETER(inHitTest);
+ UNREFERENCED_PARAMETER(inMessage);
+
+ SetCursor(LoadCursor(nullptr, IDC_HAND));
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * OnMouseMove
+ *
+ * Windows callback handler for the WM_MOUSEMOVE message
+ *
+ * @param inFlags Flags for the left button up message
+ * @param inPoint Point where the left button was last moved (client coordinates)
+ */
+//==============================================================================
+void CBaseLink::OnMouseMove(UINT inFlags, CPoint inPoint)
+{
+ UNREFERENCED_PARAMETER(inFlags);
+ UNREFERENCED_PARAMETER(inPoint);
+
+ if (IsWindowEnabled()) {
+
+ if (!m_bCapture) {
+ SetCursor(LoadCursor(nullptr, IDC_HAND));
+ SetCapture();
+
+ m_bCapture = TRUE;
+ this->ShowLink();
+ } else {
+ // Already captured...
+ if (!this->IsMouseOverLink()) {
+ m_bCapture = FALSE;
+ ReleaseCapture();
+
+ this->ShowLink();
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * IsMouseOverLink: Determine if the mouse is over the control.
+ *
+ * @param None
+ *
+ * @return true if the mouse is over the control.
+ */
+//==============================================================================
+bool CBaseLink::IsMouseOverLink()
+{
+ POINT theMousePos;
+ RECT theWndRect;
+
+ ::GetCursorPos(&theMousePos);
+ GetWindowRect(&theWndRect);
+
+ return PtInRect(&theWndRect, theMousePos) ? true : false;
+}
diff --git a/src/Authoring/Studio/_Win/Application/BaseLink.h b/src/Authoring/Studio/_Win/Application/BaseLink.h
new file mode 100644
index 00000000..4d89a155
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/BaseLink.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef _BASELINK_H_
+#define _BASELINK_H_
+
+/////////////////////////////////////////////////////////////////////////////
+// CBaseLink window
+
+class CBaseLink : public CWnd
+{
+ // Construction
+public:
+ CBaseLink();
+
+ // Attributes
+public:
+ // Operations
+public:
+protected:
+ bool m_bCapture;
+
+ virtual bool IsMouseOverLink();
+ virtual void ShowLink() = 0;
+ virtual void ShowTextLink(COLORREF inTextColor, COLORREF inBackColor, UINT inTextFormat,
+ bool inUnderlineText);
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CBaseLink)
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ virtual ~CBaseLink();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CBaseLink)
+ virtual afx_msg void OnPaint();
+ virtual afx_msg BOOL OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message);
+ virtual afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Application/MsgRouter.cpp b/src/Authoring/Studio/_Win/Application/MsgRouter.cpp
new file mode 100644
index 00000000..4ce57cc8
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/MsgRouter.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "MsgRouter.h"
+#include "StudioConst.h"
+#include "Core.h"
+#include "Doc.h"
+#include "Views.h"
+
+#include <QCoreApplication>
+
+static std::unique_ptr<CMsgRouter> static_theInstance;
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CMsgRouter::CMsgRouter()
+{
+ qApp->installEventFilter(this);
+ m_eventType = QEvent::registerEventType();
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CMsgRouter::~CMsgRouter()
+{
+}
+
+CMsgRouter *CMsgRouter::GetInstance()
+{
+ if (!static_theInstance) {
+ static_theInstance.reset(new CMsgRouter);
+ }
+
+ return static_theInstance.get();
+}
+
+//==============================================================================
+/**
+ * Send a command to be executed asynchronously.
+ */
+void CMsgRouter::SendCommand(CCmd *inCommand, CCore *inCore)
+{
+ SMessageData *theMsgData = new SMessageData(m_eventType);
+ theMsgData->Method = &CMsgRouter::OnCommand;
+ theMsgData->Data = inCommand;
+ theMsgData->Data2 = inCore;
+
+ qApp->postEvent(qApp, theMsgData);
+}
+
+bool CMsgRouter::eventFilter(QObject *watched, QEvent *event)
+{
+ if (event->type() == m_eventType) {
+ SMessageData *theMsgData = reinterpret_cast<SMessageData *>(event);
+ (this->*(theMsgData->Method))(theMsgData);
+ return true;
+ }
+
+ return false;
+}
+
+//==============================================================================
+/**
+ * Windows entry point for processing generic messages.
+ */
+void CMsgRouter::OnAsyncNotification(SMessageData *inMessageData)
+{
+ try {
+ CRoutedMessageBase *theRoutedMsg = static_cast<CRoutedMessageBase *>(inMessageData->Data);
+ if (theRoutedMsg)
+ theRoutedMsg->Notify();
+ } catch (...) {
+ // Catch crashes in case the object is gone
+ }
+}
+
+//==============================================================================
+/**
+ * Main thread processing for processing command execution messages.
+ */
+void CMsgRouter::OnCommand(SMessageData *inMsgData)
+{
+ CCmd *theCommand = static_cast<CCmd *>(inMsgData->Data);
+ CCore *theCore = static_cast<CCore *>(inMsgData->Data2);
+ theCore->ExecuteCommand(theCommand, true);
+}
+
+
+
+CMsgRouter::SMessageData::SMessageData(int eventType) :
+ QEvent(static_cast<QEvent::Type>(eventType))
+{
+}
diff --git a/src/Authoring/Studio/_Win/Application/StudioApp.cpp b/src/Authoring/Studio/_Win/Application/StudioApp.cpp
new file mode 100644
index 00000000..fa160431
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/StudioApp.cpp
@@ -0,0 +1,1835 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+#ifdef _WIN32
+#pragma warning(disable : 4100) // unreferenced formal parameter
+#endif
+#include "StudioApp.h"
+#include "SubPresentationsDlg.h"
+#include "UICStateApplication.h"
+
+#include <QtGui/qsurfaceformat.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qurl.h>
+
+int main(int argc, char *argv[])
+{
+ // to enable QOpenGLWidget to work on macOS, we must set the default
+ // QSurfaceFormat before QApplication is created. Otherwise context-sharing
+ // fails and QOpenGLWidget breaks.
+
+ // fortunately, we know which OpenGL version we can use on macOS, so we
+ // can simply hard-code it here.
+#if defined(Q_OS_MACOS)
+ QSurfaceFormat openGL33Format;
+ openGL33Format.setRenderableType(QSurfaceFormat::OpenGL);
+ openGL33Format.setProfile(QSurfaceFormat::CoreProfile);
+ openGL33Format.setMajorVersion(3);
+ openGL33Format.setMinorVersion(3);
+ openGL33Format.setStencilBufferSize(8);
+ QSurfaceFormat::setDefaultFormat(openGL33Format);
+#endif
+
+ // init runtime static resources
+ Q_INIT_RESOURCE(res);
+
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QApplication guiApp(argc, argv);
+ // Load and apply stylesheet for the application
+ QFile styleFile(":/style.qss");
+ styleFile.open(QFile::ReadOnly);
+ guiApp.setStyleSheet(styleFile.readAll());
+ g_StudioApp.InitInstance(argc, argv);
+ return g_StudioApp.Run();
+}
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Exceptions.h"
+#include "IOLibraryException.h"
+#include "Strings.h"
+#include "MainFrm.h"
+#include "AboutDlg.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "StackOps.h"
+#include "Views.h"
+#endif
+#include "StringLoader.h"
+#include "Doc.h"
+#include "Dialogs.h"
+#include "Dispatch.h"
+#include "StartupDlg.h"
+#include "RecentItems.h"
+#include "StudioPreferences.h"
+#include "MsgRouter.h"
+#include "SplashView.h"
+#include "Views.h"
+#include "UICLog.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "WinUtils.h"
+#include "CrashDlg.h"
+#endif
+#include "UICFile.h"
+#include "UICFileTools.h"
+#include "ITickTock.h"
+#include "IStudioRenderer.h"
+#include "IDocumentEditor.h"
+#include "StudioUtils.h"
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "IObjectReferenceHelper.h"
+#endif
+#include "ClientDataModelBridge.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "CommonConstants.h"
+#include "IOLibraryException.h"
+
+#ifdef _DEBUG
+#include "UICMemoryLeak.h"
+#endif
+#include "UICDMErrors.h"
+
+#include <iostream>
+#include <fstream>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#endif
+#include <string.h>
+
+#include <QApplication>
+#include <QSettings>
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "..\Build\versionnumber.h"
+
+#include "UICDESKey.h" // g_DESKey
+#endif
+
+#include "Core.h"
+#include "HotKeys.h"
+#include "StudioTutorialWidget.h"
+#include "GuideInspectable.h"
+#include "UICDMStudioSystem.h"
+#include "UICDMInspectable.h"
+#include "UICDMSlides.h"
+#include "UICDMMaterialInspectable.h"
+#include "UICDMSceneInspectable.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "UICDMAnimation.h"
+#include "UICDMDataCore.h"
+#include "SlideControl.h"
+#endif
+#include "IDirectoryWatchingSystem.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "ITickTock.h"
+#include "UICFileTools.h"
+#include "foundation/Qt3DSLogging.h"
+
+#endif
+#ifdef USE_LICENSE_HANDLER
+#include "licensehandler.h"
+#endif
+
+CStudioApp g_StudioApp;
+long g_UICErrorCode = 0;
+
+using namespace Q3DStudio;
+
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+char g_DumpPath[MAX_PATH] = { 0 };
+
+#ifndef WIN32
+namespace qt3ds
+{
+void NVAssert(const char *exp, const char *file, int line, bool *igonore)
+{
+ qFatal("NVAssertion thrown %s(%d): %s", file, line, exp);
+}
+}
+#endif
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CStudioApp::CStudioApp()
+#ifdef KDAB_TEMPORARILY_REMOVED
+ , m_SplashPalette(nullptr)
+ , m_OldHelpFilePath(nullptr)
+ , m_UnitTestResults(0)
+ , m_IsSilent(false)
+ , m_Core(NULL)
+ , m_Views(NULL)
+ , m_Dialogs(NULL)
+ , m_ManipulationMode(StudioManipulationModes::Local)
+ , m_PlaybackTime(0)
+ , m_pGdiToken(0)
+ , m_AuthorZoom(false)
+#endif
+ : m_ToolMode(STUDIO_TOOLMODE_MOVE)
+ , m_SelectMode(STUDIO_SELECTMODE_GROUP)
+ , m_welcomeShownThisSession(false)
+ , m_goStraightToWelcomeFileDialog(false)
+ , m_tutorialPage(0)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+#ifdef _DEBUG
+ AfxEnableMemoryTracking(TRUE);
+ CMemoryLeak::SetXMLFileName("StudioMemoryLeaks.xml");
+ CMemoryLeak::SetShowDialogOnExit(false);
+#endif // _DEBUG
+ g_DumpPath[0] = 0;
+#endif
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CStudioApp::~CStudioApp()
+{
+ // Do not call PerformShutdown from here as the C has already been shutdown (!!)
+}
+
+void CStudioApp::PerformShutdown()
+{
+ m_DirectoryWatcherTicker = std::shared_ptr<UICDM::ISignalConnection>();
+
+ // Dispatch un-registration
+ if (m_Core) {
+ m_Core->GetDispatch()->RemoveAppStatusListener(this);
+ m_Core->GetDispatch()->RemoveCoreAsynchronousEventListener(this);
+ qCInfo(qt3ds::TRACE_INFO) << "Studio exiting successfully";
+ }
+
+ if (m_Renderer) {
+ m_Renderer->Close();
+ m_Renderer = std::shared_ptr<Q3DStudio::IStudioRenderer>();
+ }
+
+ // No need to delete m_SplashPalette. You should not call delete on CFrameWnds,
+ // you should call DestroyWindow( ) instead. See the MSDN.
+ // delete m_SplashPalette;
+#ifdef KDAB_TEMPORARILY_REMOVED
+ delete m_Views;
+ m_Views = nullptr;
+ delete m_Dialogs;
+ m_Dialogs = nullptr;
+ delete m_Core;
+ m_Core = nullptr;
+#endif
+
+ CStringLoader::UnloadStrings();
+
+ // Get rid of the temp files
+ CUICFile::ClearCurrentTempCache();
+
+ qApp->exit();
+}
+
+//=============================================================================
+/**
+ * Entry location for the creation of this application.
+ * This creates the all the views, then returns if everything
+ * was successful.
+ */
+BOOL CStudioApp::InitInstance(int argc, char* argv[])
+{
+ QApplication::setOrganizationName("The Qt Company");
+ QApplication::setOrganizationDomain("qt.io");
+ QApplication::setApplicationName("Qt 3D Studio");
+ QApplication::setApplicationVersion(
+ QString::fromWCharArray(CStudioPreferences::GetVersionString().c_str()));
+
+ qCInfo(qt3ds::TRACE_INFO) << "Studio: " << QApplication::applicationFilePath();
+
+ // Load the strings used by the app gui
+ // This needs to occur prior to parsing command line arguments
+ // since access to the strings are required by some of the cases
+ CUICFile theResDir(CString::fromQString(resourcePath() + QStringLiteral("/strings")));
+ CStringLoader::LoadStrings(theResDir);
+ qCInfo(qt3ds::TRACE_INFO) << "Version: "
+ << CStudioPreferences::GetVersionString().GetCharStar();
+
+ std::vector<wchar_t*> wargv;
+ wargv.resize(argc);
+ for (int i = 0; i < argc; ++i) {
+ QString arg = argv[i];
+ wargv[i] = new wchar_t[arg.size() + 1];
+ wargv[i][arg.size()] = L'\0';
+ arg.toWCharArray(wargv[i]);
+ }
+
+ // Parse the command line so we know what's up
+ m_CmdLineParser.ParseArguments(argc, &(wargv[0]));
+
+ // Silent mode indicates that Studio will be operated in a muted "no-GUI" mode
+ m_IsSilent = m_CmdLineParser.IsSilent();
+
+ // If we're just running unit tests, return before creating windows/MFC controls
+ if (m_CmdLineParser.IsRunUnitTests()) {
+ {
+ RunCmdLineTests(m_CmdLineParser.GetFilename());
+ return FALSE; // return false so we bail from loading the app
+ }
+ }
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need
+ // Change the registry key under which our settings are stored
+ Q3DStudio::CString theRegistryKey =
+ ::LoadResourceString(IDS_UICOMPOSER_PALETTE_SETTINGS_REGISTRY_KEY);
+ SetRegistryKey(theRegistryKey);
+#endif
+
+ CFilePath thePreferencesPath = CFilePath::GetUserApplicationDirectory();
+ thePreferencesPath = CFilePath::CombineBaseAndRelative(
+ thePreferencesPath, CFilePath(L"UIComposer\\Preferences.setting"));
+ CPreferences::SetPreferencesFile(thePreferencesPath);
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Set up the path to the help file
+ InitHelpSystem();
+#endif
+
+ CStudioPreferences::LoadPreferences();
+
+ m_Dialogs = new CDialogs(!m_IsSilent);
+
+ if (!m_IsSilent) {
+ // Show the splash screen
+ m_SplashPalette = new CSplashView();
+ m_SplashPalette->setWindowTitle(::LoadResourceString(IDS_PROJNAME).toQString());
+ m_SplashPalette->show();
+
+ m_Views = new CViews(this);
+ }
+
+ // All custom icons (PNGs) are drawn using Gdiplus so that transparency are handled.
+ // note that gdiplus.dll are included with WinXP ( previous OS versions require the gdi
+ // redistributables to be installed and unless
+ // support for those OS becomes a priority, we assume Studio is run minimally on a XP machine )
+#ifdef KDAB_TEMPORARILY_REMOVED
+ Gdiplus::GdiplusStartup(&m_pGdiToken, &m_gdiplusStartupInput, nullptr); // gdi+ init
+#endif
+
+ m_Core = new CCore();
+ GetRenderer();
+ m_Core->GetDoc()->SetSceneGraph(m_Renderer);
+
+ // Dispatch registration
+ m_Core->GetDispatch()->AddAppStatusListener(this);
+ m_Core->GetDispatch()->AddCoreAsynchronousEventListener(this);
+
+ return TRUE;
+}
+
+//=============================================================================
+/**
+ * Exit location for the destruction of this application.
+ * @return 0 on success; -1 on failure
+ */
+int CStudioApp::ExitInstance()
+{
+ int theResult = -1;
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // CWinApp::InitInstance returns 1(TRUE) on success; 0(FALSE) on failure
+ if (CWinApp::InitInstance() == TRUE)
+ theResult = 0;
+
+ if (m_CmdLineParser.IsRunUnitTests() && 0 == m_UnitTestResults)
+ theResult = m_UnitTestResults; // unit tests return 0 on success; 1 on failure
+
+#ifdef _DEBUG
+ // If appears that MFC takes over dumping memory leaks on exit
+ // this is the only way I've been able to turn it off.
+
+ // Turn off dumping CRT memory leaks
+ ::_CrtSetReportMode(_CRT_WARN, 0);
+ ::_CrtSetReportMode(_CRT_ERROR, 0);
+ ::_CrtSetReportMode(_CRT_ASSERT, 0);
+#endif
+
+ // Make sure any GDI resources have been cleaned up
+ CResourceCache::GetInstance()->Clear();
+ // Called in conjuction with Gdiplus::GdiplusStartup
+ Gdiplus::GdiplusShutdown(m_pGdiToken);
+#endif
+
+ return theResult;
+}
+
+//=============================================================================
+/**
+ * Command handler to display the about dialog.
+ */
+void CStudioApp::OnAppAbout()
+{
+ CAboutDlg aboutDlg;
+ aboutDlg.exec();
+}
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+//=============================================================================
+/**
+ * Overrides registry access member functions, direct settings to a XML file
+ */
+UINT CStudioApp::GetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault)
+{
+ QT3DS_ASSERT(lpszSection != nullptr);
+ QT3DS_ASSERT(lpszEntry != nullptr);
+
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection);
+ return CPreferences::GetUserPreferences(theSubKeyName).GetLongValue(lpszEntry, nDefault);
+}
+BOOL CStudioApp::WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue)
+{
+ QT3DS_ASSERT(lpszSection != nullptr);
+ QT3DS_ASSERT(lpszEntry != nullptr);
+
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection);
+ CPreferences::GetUserPreferences(theSubKeyName).SetLongValue(lpszEntry, nValue);
+ return TRUE;
+}
+::CString CStudioApp::GetProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry,
+ LPCTSTR lpszDefault /* = nullptr */)
+{
+ QT3DS_ASSERT(lpszSection != nullptr);
+ QT3DS_ASSERT(lpszEntry != nullptr);
+
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection);
+ return CPreferences::GetUserPreferences(theSubKeyName).GetStringValue(lpszEntry, lpszDefault);
+}
+BOOL CStudioApp::WriteProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue)
+{
+ QT3DS_ASSERT(lpszSection != nullptr);
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection);
+
+ if (lpszEntry == nullptr) // delete whole section
+ {
+ CPreferences::GetUserPreferences(theSubKeyName).Clear();
+ } else if (lpszValue == nullptr) {
+ CPreferences::GetUserPreferences(theSubKeyName).RemoveKey(lpszEntry);
+ } else {
+ CPreferences::GetUserPreferences(theSubKeyName).SetStringValue(lpszEntry, lpszValue);
+ }
+ return TRUE;
+}
+#endif
+
+//=============================================================================
+/**
+ * Main application execution loop.
+ * The application's main thread stays in this until the app exits.
+ * @return 0 on success; -1 on failure
+ */
+int CStudioApp::Run()
+{
+ int theRetVal = -1;
+
+#ifdef USE_LICENSE_HANDLER
+ LicenseHandler lh;
+ if (!lh.handleLicense())
+ return theRetVal;
+#endif
+
+ try {
+ UIC_LOGSTART;
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Set the crash handler for all unhandled exceptions.
+ CStackOps::SetCrashProc(&StudioUnhandledCrashHandler);
+ CStackOps::RegisterCrashHandler();
+ CStackOps::EnableCrashingOnCrashes();
+#endif
+
+ CCmdLineParser::EExecutionMode theMode = m_CmdLineParser.PopExecutionMode();
+ if (CCmdLineParser::END_OF_CMDS == theMode)
+ theMode = CCmdLineParser::NORMAL;
+
+ for (; CCmdLineParser::END_OF_CMDS != theMode;
+ theMode = m_CmdLineParser.PopExecutionMode()) {
+ // This just switches the execution mode of the app and starts it in the correct state.
+ switch (theMode) {
+ case CCmdLineParser::TEST_CMD_LINE:
+ theRetVal = RunSystemTests(m_CmdLineParser.GetFilename());
+ break;
+ case CCmdLineParser::OPEN_FILE:
+ theRetVal = OpenAndRunApplication(m_CmdLineParser.GetFilename());
+ break;
+ default:
+ theRetVal = BlankRunApplication();
+ break;
+ }
+
+ // if any operations returned a bad value, stop following operations
+ if (-1 == theRetVal)
+ break;
+ }
+ PerformShutdown();
+
+ UIC_LOGSTOP;
+ } catch (CUICExceptionClass &inException) {
+ g_UICErrorCode = inException.GetErrorCode();
+ throw;
+ } catch (UICDM::UICDMError &uicdmError) {
+ Q_UNUSED(uicdmError);
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ EXCEPTION_POINTERS *pExPtrs;
+ CStackOps::GetExceptionPointers(1, &pExPtrs);
+ StudioUnhandledCrashHandler(pExPtrs);
+#endif
+ exit(1);
+ } catch (...) {
+ throw;
+ }
+
+ return theRetVal;
+}
+
+bool CStudioApp::HandleWelcomeRes(int res, bool recursive)
+{
+ int theReturn = true;
+ switch (res) {
+ case StudioTutorialWidget::createNewResult: {
+ std::pair<CUICFile, bool> theFile = m_Dialogs->
+ GetNewDocumentChoice(Q3DStudio::CString("."));
+ if (theFile.first.GetPath() != "") {
+ m_Core->OnNewDocument(theFile.first, theFile.second);
+ theReturn = true;
+ m_welcomeShownThisSession = true;
+ } else {
+ // User Cancels the dialog. Show the welcome screen.
+ if (recursive) {
+ m_welcomeShownThisSession = false;
+ m_goStraightToWelcomeFileDialog = true;
+ theReturn = ShowStartupDialog();
+ } else {
+ theReturn = false;
+ }
+ }
+ } break;
+
+ case StudioTutorialWidget::openSampleResult: {
+ // Try three options:
+ // - open a specific example directory with .uip file in it
+ // - failing that, show the main example root dir
+ // - failing all previous, show Qt3DStudio dir
+ Q3DStudio::CFilePath filePath;
+
+ filePath = CUICFile::GetApplicationDirectory().GetPath()+
+ Q3DStudio::CString("../examples/qmldynamickeyframes/presentation");
+
+ if (!filePath.Exists()) {
+ filePath = CUICFile::GetApplicationDirectory().GetPath()+
+ Q3DStudio::CString("../examples");
+ }
+ if (!filePath.Exists()) {
+ filePath = CUICFile::GetApplicationDirectory().GetPath()+
+ Q3DStudio::CString(".");
+ }
+
+ CUICFile theFile = m_Dialogs->GetFileOpenChoice(filePath);
+
+ if (theFile.GetPath() != "") {
+ OnLoadDocument(theFile);
+ theReturn = true;
+ m_welcomeShownThisSession = true;
+ } else {
+ // User Cancels the dialog. Show the welcome screen.
+ if (recursive) {
+ m_welcomeShownThisSession = false;
+ m_goStraightToWelcomeFileDialog = true;
+ theReturn = ShowStartupDialog();
+ } else {
+ theReturn = false;
+ }
+ }
+ } break;
+
+ default:
+ ASSERT(false); // Should not reach this block.
+ theReturn = false;
+ break;
+ }
+ return theReturn;
+}
+
+//=============================================================================
+/**
+ * Show startup dialog and perform necessary action such as create new doc or load doc.
+ * Return false if user requests to exit
+ */
+bool CStudioApp::ShowStartupDialog()
+{
+ int welcomeRes = QDialog::Rejected;
+ bool theReturn = true;
+
+ if (!m_welcomeShownThisSession){
+ m_welcomeShownThisSession = true;
+
+ bool show = false;
+ QSettings settings;
+
+ if (!settings.contains("showWelcomeScreen")) {
+ settings.setValue("showWelcomeScreen", 1);
+ show = true;
+ } else {
+ // if we are returning to welcome dialog page after canceling
+ // file dialog, do not care about settings but always show
+ // welcome
+ show = settings.value("showWelcomeScreen").toBool()
+ || m_goStraightToWelcomeFileDialog;
+ }
+
+ if (show) {
+ StudioTutorialWidget tutorial(m_goStraightToWelcomeFileDialog);
+ welcomeRes = tutorial.exec();
+ }
+ }
+
+ // show the usual startup dialog only if user rejected tutorial
+ // ( = did not open samples or create new project)
+ if (welcomeRes == QDialog::Rejected) {
+ CStartupDlg theStartupDlg;
+
+ // Populate recent items
+ Q3DStudio::CFilePath theMostRecentDirectory;
+ if (m_Views) {
+ CRecentItems *theRecentItems = m_Views->GetMainFrame()->GetRecentItems();
+ for (long theIndex = 0; theIndex < theRecentItems->GetItemCount(); ++theIndex) {
+ if (theIndex == 0) {
+ theMostRecentDirectory =
+ Q3DStudio::CFilePath(theRecentItems->GetItem(0).GetAbsolutePath())
+ .GetDirectory();
+ }
+ theStartupDlg.AddRecentItem(theRecentItems->GetItem(theIndex));
+ }
+ }
+
+ theStartupDlg.exec();
+ CStartupDlg::EStartupChoice theChoice = theStartupDlg.GetChoice();
+
+ switch (theChoice) {
+ case CStartupDlg::EStartupChoice_Exit:
+ theReturn = false;
+ break;
+
+ case CStartupDlg::EStartupChoice_NewDoc: {
+ std::pair<CUICFile, bool> theFile = m_Dialogs->
+ GetNewDocumentChoice(theMostRecentDirectory);
+ if (theFile.first.GetPath() != "") {
+ m_Core->OnNewDocument(theFile.first, theFile.second);
+ theReturn = true;
+ } else {
+ // User Cancels the dialog. Show startup dialog again.
+ theReturn = ShowStartupDialog();
+ }
+ } break;
+
+ case CStartupDlg::EStartupChoice_OpenDoc: {
+ CUICFile theFile = m_Dialogs->GetFileOpenChoice(theMostRecentDirectory);
+ if (theFile.GetPath() != "") {
+ OnLoadDocument(theFile);
+ theReturn = true;
+ } else {
+ // User Cancels the dialog. Show startup dialog again.
+ theReturn = ShowStartupDialog();
+ }
+ } break;
+
+ case CStartupDlg::EStartupChoice_OpenRecent: {
+ CUICFile theFile = theStartupDlg.GetRecentDoc();
+ if (theFile.GetPath() != "") {
+ OnLoadDocument(theFile);
+ // throw SlideNotFound( L"");
+ theReturn = true;
+ } else {
+ // User Cancels the dialog. Show startup dialog again.
+ theReturn = ShowStartupDialog();
+ }
+ } break;
+
+ default:
+ ASSERT(false); // Should not reach this block.
+ theReturn = false;
+ break;
+ }
+ } else { // open sample or create new
+ theReturn = HandleWelcomeRes(welcomeRes, true);
+ }
+ return theReturn;
+}
+
+//=============================================================================
+/**
+ * Start the app.
+ */
+int CStudioApp::BlankRunApplication()
+{
+ InitCore();
+
+ if (ShowStartupDialog())
+ return RunApplication();
+ return -1;
+}
+
+//=============================================================================
+/**
+ * Run the unit tests specified on the command line then return.
+ * @param inTestPath input unit test path
+ * @return 0 on success; 1 on failure
+ */
+int CStudioApp::RunCmdLineTests(const Q3DStudio::CString &inTestPath)
+{
+ Q_UNUSED(inTestPath);
+
+ return m_UnitTestResults;
+}
+
+//=============================================================================
+/**
+ * Run the system level tests specified on the command line then return.
+ * @param inTestPath
+ * @return 0 on success; -1 on failure
+ */
+int CStudioApp::RunSystemTests(const Q3DStudio::CString &inTestPath)
+{
+ int theSystemTestsResult = -1;
+
+ Q_UNUSED(inTestPath);
+
+ if (0 == m_UnitTestResults)
+ theSystemTestsResult = m_UnitTestResults; // unit tests return 0 on success; 1 on failure
+
+ return theSystemTestsResult;
+}
+
+//=============================================================================
+/**
+ * Open the specified file and run the application.
+ * This will load the file then go into the standard app loop.
+ * On load with the -silent flag, this would force the application to exit on
+ * load failures.
+ * @return 0 on success; -1 on failure
+ */
+int CStudioApp::OpenAndRunApplication(const Q3DStudio::CString &inFilename)
+{
+ int theSuccess = -1;
+ InitCore();
+ if (OnLoadDocument(
+ inFilename,
+ false)) // Load document. Upon failure, don't show startup dialog but exit immediately.
+ theSuccess = RunApplication();
+ return theSuccess;
+}
+
+//=============================================================================
+/**
+ * This is the app execution loop, the main thread loops here until the app exits.
+ * @return 0 on success; -1 on failure
+ */
+int CStudioApp::RunApplication()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ BOOL bIdle = TRUE;
+ LONG lIdleCount = 0;
+ MSG theMessage;
+
+ // CStackOps::RegisterCrashHandler( );
+
+ // acquire and dispatch messages until a WM_QUIT message is received.
+ for (;;) {
+ // phase1: check to see if we can do idle work
+ while (bIdle && !::PeekMessage(&theMessage, nullptr, nullptr, nullptr, PM_NOREMOVE)) {
+ // call OnIdle while in bIdle state
+ if (!OnIdle(lIdleCount++))
+ bIdle = FALSE; // assume "no idle" state
+ }
+
+ // phase2: pump messages while available
+ do {
+ try {
+ // Pump message, but quit on WM_QUIT
+ if (!PumpMessage())
+ return ExitInstance();
+ } catch (...) {
+ // Throw here so that any crash goes through the crash reporter
+ throw;
+ }
+
+ // Reset "no idle" state after pumping "normal" message
+ if (IsIdleMessage(&theMessage)) {
+ bIdle = TRUE;
+ lIdleCount = 0;
+ }
+ } while (::PeekMessage(&theMessage, nullptr, nullptr, nullptr, PM_NOREMOVE));
+ }
+#endif
+ return qApp->exec();
+}
+
+//=============================================================================
+/**
+ * Initialize the core and all the views.
+ */
+void CStudioApp::InitCore()
+{
+ // Initialize and cache the RenderSelector values for the first time,
+ // this way, subsequent attempts to instantiate a RenderSelector would circumvent the need
+ // for any extra (unneccesary) creation of render contexts which inadvertently cause exceptions
+ // to be thrown.
+
+ m_Core->Initialize();
+
+ if (m_Views) {
+ m_Views->CreateViews();
+ m_pMainWnd = m_Views->GetMainFrame();
+ } else {
+ ASSERT(0); // No views? wha?
+ }
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CMsgRouter::GetInstance()->SetMainframe(m_pMainWnd);
+#endif
+
+ // At this point, get rid of the splash screen, otherwise any errors dialog would be hidden
+ // behind.
+ // Could happen when this is directly activated due to a uip file being dbl-clicked or dragged
+ // into the executable.
+ if (m_SplashPalette) {
+ m_SplashPalette->deleteLater();
+ m_SplashPalette = nullptr;
+ }
+
+ RegisterGlobalKeyboardShortcuts(m_Core->GetHotKeys());
+ m_Core->GetDispatch()->AddPresentationChangeListener(this);
+}
+
+struct SIImportFailedHandler : public Q3DStudio::IImportFailedHandler
+{
+ CDialogs &m_Dialogs;
+ SIImportFailedHandler(CDialogs &dialogs)
+ : m_Dialogs(dialogs)
+ {
+ }
+ void DisplayImportFailed(const QString &inDocumentPath,
+ const QString &inDescription, bool inWarningsOnly) override
+ {
+ m_Dialogs.DisplayImportFailed(QUrl(inDocumentPath), inDescription, inWarningsOnly);
+ }
+};
+
+struct SIDeletingReferencedObjectHandler : public Q3DStudio::IDeletingReferencedObjectHandler
+{
+ CDialogs &m_Dialogs;
+
+ SIDeletingReferencedObjectHandler(CDialogs &dialogs)
+ : m_Dialogs(dialogs)
+ {
+ }
+
+ void DisplayMessageBox(const Q3DStudio::CString &inDescription) override
+ {
+ Q3DStudio::CString theTitle(::LoadResourceString(IDS_DELETE_OBJ_CONFIRM_TITLE));
+ Q3DStudio::CString theFormat(::LoadResourceString(IDS_DELETE_OBJ_CONFIRM_MSG));
+ Q3DStudio::CString theMessage;
+ theMessage.Format(theFormat, static_cast<const wchar_t *>(inDescription));
+
+ m_Dialogs.DisplayMessageBox(theTitle, theMessage, CUICMessageBox::ICON_WARNING, false);
+ }
+};
+
+void CStudioApp::SetupTimer(long inMessageId, QWidget *inWnd)
+{
+ m_TickTock = ITickTock::CreateTickTock(inMessageId, inWnd);
+ GetDirectoryWatchingSystem();
+ m_Core->GetDoc()->SetDirectoryWatchingSystem(m_DirectoryWatchingSystem);
+ m_Core->GetDoc()->SetImportFailedHandler(
+ std::make_shared<SIImportFailedHandler>(std::ref(*GetDialogs())));
+ m_Core->GetDoc()->SetDocMessageBoxHandler(
+ std::make_shared<SIDeletingReferencedObjectHandler>(std::ref(*GetDialogs())));
+}
+
+ITickTock &CStudioApp::GetTickTock()
+{
+ if (m_TickTock == nullptr)
+ throw std::runtime_error("Uninitialized TickTock");
+ return *m_TickTock;
+}
+
+Q3DStudio::IStudioRenderer &CStudioApp::GetRenderer()
+{
+ if (!m_Renderer)
+ m_Renderer = Q3DStudio::IStudioRenderer::CreateStudioRenderer();
+ return *m_Renderer;
+}
+
+void CStudioApp::ClearGuides()
+{
+ SCOPED_DOCUMENT_EDITOR(*m_Core->GetDoc(), QObject::tr("Clear Guides"))->ClearGuides();
+}
+
+void SendAsyncCommand(CDispatch &inDispatch, Q3DStudio::TCallbackFunc inFunc)
+{
+ inDispatch.FireOnAsynchronousCommand(inFunc);
+}
+
+IDirectoryWatchingSystem &CStudioApp::GetDirectoryWatchingSystem()
+{
+ if (m_DirectoryWatchingSystem == nullptr) {
+ Q3DStudio::TCallbackCaller theCaller =
+ std::bind(SendAsyncCommand, std::ref(*m_Core->GetDispatch()), std::placeholders::_1);
+ m_DirectoryWatchingSystem =
+ IDirectoryWatchingSystem::CreateThreadedDirectoryWatchingSystem(theCaller);
+ }
+ return *m_DirectoryWatchingSystem;
+}
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+bool s_testVar = true;
+//==============================================================================
+/**
+ * This gets called any time an unhandled exception is thrown anywhere in the
+ * application.
+ *
+ * @param pExPtrs a description of the exception.
+ * @return 0 if not handled, 1 if it was handled.
+ */
+void CStudioApp::StudioUnhandledCrashHandler(EXCEPTION_POINTERS *pExPtrs)
+{
+ TCHAR theTraceBuffer[4096];
+ CCrashDlg theDlg;
+ Q3DStudio::CString errorMessage;
+
+ CStackOps::GetExceptionStackTrace(theTraceBuffer, sizeof(theTraceBuffer),
+ pExPtrs->ContextRecord);
+ if (g_UICErrorCode != 0) {
+ // switch (g_UICErrorCode)
+ //{
+ // default:
+ Q3DStudio::CString description;
+ description.Format(_UIC("Custom error 0x%X "), g_UICErrorCode);
+ errorMessage = CStackOps::GetExceptionDescription(description, pExPtrs);
+ // break;
+ //}
+ } else {
+ errorMessage = CStackOps::GetExceptionDescription(pExPtrs);
+ }
+ theDlg.SetStackTrace(theTraceBuffer);
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Crash!" << theTraceBuffer;
+ // Attempt to save the current project (although this may crash).
+ CDoc &theDoc = *g_StudioApp.m_Core->GetDoc();
+ CFilePath theFullPath = theDoc.GetDocumentPath().GetAbsolutePath();
+ CFilePath theDir = theFullPath.GetDirectory();
+ CFilePath theStem = theFullPath.GetFileStem();
+ theStem.append(L"_Crash");
+ // Attempt to open a dump file ideally next to the log file.
+ CFilePath theSaveFile;
+ {
+ TFilePtr theSaveFilePtr =
+ SFileTools::FindUniqueDestFile(theDir, theStem, CFilePath(L"uip"));
+ theSaveFile = theSaveFilePtr->m_Path;
+ }
+ theSaveFile.DeleteThisFile();
+ theDoc.SaveDocument(CUICFile(theSaveFile));
+ qCInfo(qt3ds::TRACE_INFO) << "Project successfully saved: " << theSaveFile.GetCharStar();
+
+ ::CString fileSaveLocationMessage;
+ fileSaveLocationMessage.Format(L"Project saved as %ls",
+ static_cast<const wchar_t *>(theSaveFile));
+
+ theDlg.SetErrorMessage(errorMessage);
+ theDlg.SetFilename(fileSaveLocationMessage);
+ theDlg.DoModal();
+}
+
+void CStudioApp::InitHelpSystem()
+{
+ Q3DStudio::CString theHelpFile = ::LoadResourceString(IDS_HELP_FILE_NAME);
+
+ ATL::CStringT<TCHAR, StrTraitMFC<TCHAR>> theOldHelpPath(m_pszHelpFilePath);
+ ATL::CStringT<TCHAR, StrTraitMFC<TCHAR>> theNewHelpPath;
+
+ long theIndex = theOldHelpPath.ReverseFind('\\');
+ theOldHelpPath.Delete(theIndex + 1, (theOldHelpPath.GetLength() - theIndex));
+ theNewHelpPath = theOldHelpPath;
+ ::CString theMFCHelpFile(theHelpFile.GetMulti());
+ theNewHelpPath += theMFCHelpFile;
+
+ // Save the m_pszHelpFilePath variable so that CWinApp::SetCurrentHandles()
+ // in appinit.cpp can deallocate the memory it allocated, which causes a
+ // mmgr.h assert when we free it in here
+ m_OldHelpFilePath = const_cast<LPTSTR>(m_pszHelpFilePath);
+
+ long theLength = theNewHelpPath.GetLength();
+ m_pszHelpFilePath = new TCHAR[theLength + 1];
+ ::lstrcpyn(const_cast<LPTSTR>(m_pszHelpFilePath), theNewHelpPath, theLength + 1);
+}
+#endif
+
+CCore *CStudioApp::GetCore()
+{
+ return m_Core;
+}
+
+//=============================================================================
+/**
+ * Get the view manager for this core to communicate to the views.
+ */
+CViews *CStudioApp::GetViews()
+{
+ return m_Views;
+}
+
+//=============================================================================
+/**
+ * Get the dialog manager for this core for displaying dialogs.
+ */
+CDialogs *CStudioApp::GetDialogs()
+{
+ return m_Dialogs;
+}
+
+long CStudioApp::GetToolMode()
+{
+ return m_ToolMode;
+}
+
+void CStudioApp::SetToolMode(long inToolMode)
+{
+ if (m_ToolMode != inToolMode) {
+ m_ToolMode = inToolMode;
+ m_Core->GetDispatch()->FireOnToolbarChange();
+ }
+}
+
+long CStudioApp::GetSelectMode()
+{
+ return m_SelectMode;
+}
+
+void CStudioApp::SetSelectMode(long inSelectMode)
+{
+ if (m_SelectMode != inSelectMode) {
+ m_SelectMode = inSelectMode;
+ m_Core->GetDispatch()->FireOnToolbarChange();
+ }
+}
+
+StudioManipulationModes::Enum CStudioApp::GetMinpulationMode() const
+{
+ return m_ManipulationMode;
+}
+void CStudioApp::SetMinpulationMode(StudioManipulationModes::Enum inManipulationMode)
+{
+ if (m_ManipulationMode != inManipulationMode) {
+ m_ManipulationMode = inManipulationMode;
+ m_Core->GetDispatch()->FireOnToolbarChange();
+ }
+}
+
+//=============================================================================
+/**
+ * return true if undo is possible
+ */
+bool CStudioApp::CanUndo()
+{
+ return m_Core->GetCmdStack()->CanUndo();
+}
+
+//=============================================================================
+/**
+ * return true if redo is possible
+ */
+bool CStudioApp::CanRedo()
+{
+ return m_Core->GetCmdStack()->CanRedo();
+}
+
+void CStudioApp::OnCopy()
+{
+ m_Core->GetDoc()->HandleCopy();
+}
+
+bool CStudioApp::CanCopy()
+{
+ return m_Core->GetDoc()->CanCopy();
+}
+
+//=============================================================================
+/**
+ * Get a string describing the type of the copy operation that can be done.
+ * Precedence of copying is 1) Actions; 2) Keyframes; 3) Objects
+ */
+Q3DStudio::CString CStudioApp::GetCopyType()
+{
+ Q3DStudio::CString theCopyType;
+
+ CDoc *theDoc = m_Core->GetDoc();
+ if (theDoc->CanCopyAction())
+ theCopyType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_ACTION);
+ else if (theDoc->CanCopyKeyframe())
+ theCopyType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_KEYFRAMES);
+ else
+ theCopyType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_OBJECT);
+
+ return theCopyType;
+}
+
+//=============================================================================
+/**
+ * Cuts the selected object or keys
+ */
+void CStudioApp::OnCut()
+{
+ m_Core->GetDoc()->HandleCut();
+}
+
+bool CStudioApp::CanCut()
+{
+ return m_Core->GetDoc()->CanCut();
+}
+
+//=============================================================================
+/**
+ * Paste keys from the copied list yo
+ */
+void CStudioApp::OnPaste()
+{
+ m_Core->GetDoc()->HandlePaste();
+}
+
+bool CStudioApp::CanPaste()
+{
+ return m_Core->GetDoc()->CanPaste();
+}
+
+//=============================================================================
+/**
+ * Get a string describing the type of the paste operation that can be done.
+ * Precedence of paste is 1) Actions; 2) Object ; 3) Keyframes
+ */
+Q3DStudio::CString CStudioApp::GetPasteType()
+{
+ Q3DStudio::CString thePasteType;
+
+ CDoc *theDoc = m_Core->GetDoc();
+ if (theDoc->CanPasteAction())
+ thePasteType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_ACTION);
+ else if (theDoc->CanPasteObject())
+ thePasteType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_OBJECT);
+ else
+ thePasteType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_KEYFRAMES);
+
+ return thePasteType;
+}
+
+bool CStudioApp::CanChangeTimebarColor()
+{
+ bool theRetVal = true;
+ UICDM::CUICDMInstanceHandle theSelectedInstance = m_Core->GetDoc()->GetSelectedInstance();
+ if (!theSelectedInstance.Valid()
+ || m_Core->GetDoc()->GetStudioSystem()->GetClientDataModelBridge()->IsSceneInstance(
+ theSelectedInstance))
+ theRetVal = false;
+
+ return theRetVal;
+}
+
+//=============================================================================
+/**
+ * Sets any changed keyframes on the selected object
+ */
+void CStudioApp::HandleSetChangedKeys()
+{
+ m_Core->GetDoc()->SetChangedKeyframes();
+}
+
+//=============================================================================
+/**
+ * Deletes all selected keys
+ */
+void CStudioApp::DeleteSelectedKeys()
+{
+ m_Core->GetDoc()->DeleteSelectedKeys();
+}
+
+//=============================================================================
+/**
+ * Handles the duplicate object command
+ */
+void CStudioApp::HandleDuplicateCommand()
+{
+ m_Core->GetDoc()->HandleDuplicateCommand();
+}
+
+//=============================================================================
+/**
+ * return true if the selected object is duplicatable
+ */
+bool CStudioApp::CanDuplicateObject()
+{
+ // Get the currently selected object
+ UICDM::CUICDMInstanceHandle theSelectedInstance = m_Core->GetDoc()->GetSelectedInstance();
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Check if the object can be duplicated
+ return m_Core->GetDoc()->GetStudioSystem()->GetClientDataModelBridge()->IsDuplicateable(
+ theSelectedInstance);
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * Toggles the state of autoset keyframes.
+ */
+void CStudioApp::OnToggleAutosetKeyframes()
+{
+ SetAutosetKeyframes(!CStudioPreferences::IsAutosetKeyframesOn());
+
+ m_Core->GetDispatch()->FireOnToolbarChange();
+}
+
+//==============================================================================
+/**
+ * Updates the preferences, and AnimationSystem.
+ */
+void CStudioApp::SetAutosetKeyframes(bool inFlag)
+{
+ CStudioPreferences::SetAutosetKeyframesOn(inFlag);
+
+ m_Core->GetDoc()->GetStudioSystem()->GetAnimationSystem()->SetAutoKeyframe(inFlag);
+}
+
+//==============================================================================
+/**
+ * If the presentation is not currently playing, this function will make it
+ * start playing from the current position. The starting point of the playhead
+ * is saved so that it can be restored later.
+ */
+void CStudioApp::PlaybackPlay()
+{
+ CDoc *theDoc = m_Core->GetDoc();
+ if (!theDoc->IsPlaying()) {
+ m_PlaybackTime = theDoc->GetCurrentViewTime();
+ m_PlaybackOriginalSlide = theDoc->GetActiveSlide();
+ theDoc->SetPlayMode(PLAYMODE_PLAY);
+ }
+}
+
+//==============================================================================
+/**
+ * If the presentation is currently playing, it is stopped. The playhead is
+ * left wherever it was stopped at (hence it's not restored).
+ */
+void CStudioApp::PlaybackStopNoRestore()
+{
+ m_Core->GetDoc()->SetPlayMode(PLAYMODE_STOP);
+}
+
+//==============================================================================
+/**
+ * Moves the playhead back to time zero.
+ */
+void CStudioApp::PlaybackRewind()
+{
+ CDoc *theDoc = m_Core->GetDoc();
+ if (theDoc->IsPlaying()) {
+ theDoc->SetPlayMode(PLAYMODE_STOP, 0);
+ theDoc->SetPlayMode(PLAYMODE_PLAY);
+ } else {
+ m_Core->GetDoc()->NotifyTimeChanged(0);
+ }
+}
+
+//=============================================================================
+/**
+ * Performs a file revert.
+ * This will revert the doc to the last saved version.
+ */
+void CStudioApp::OnRevert()
+{
+ if (!m_Core->GetDoc()->IsModified() || m_Dialogs->ConfirmRevert()) {
+ CUICFile theCurrentDoc = m_Core->GetDoc()->GetDocumentPath();
+ OnLoadDocument(theCurrentDoc);
+ }
+}
+
+//=============================================================================
+/**
+ * Check to see if it is possible to perform a revert.
+ */
+bool CStudioApp::CanRevert()
+{
+ return m_Core->GetDoc()->IsModified() && m_Core->GetDoc()->GetDocumentPath().GetPath() != "";
+}
+
+//==============================================================================
+/**
+ * Handles the recent list.
+ */
+void CStudioApp::OnFileOpenRecent(const CUICFile &inDocument)
+{
+ if (PerformSavePrompt())
+ OnLoadDocument(inDocument);
+}
+
+//==============================================================================
+/**
+ * Called when closing the current doc, this prompts the user to save the doc.
+ * This will only prompt if the doc is modified, and if the user selects save
+ * then this will perform the save operation.
+ * @return true if the operation should continue, false if not.
+ */
+bool CStudioApp::PerformSavePrompt()
+{
+ if (m_Core->GetDoc()->IsModified()) {
+ CDialogs::ESavePromptResult theResult = m_Dialogs->PromptForSave();
+ if (theResult == CDialogs::SAVE_FIRST) {
+ bool onSaveResult = OnSave();
+ if (onSaveResult)
+ return true;
+ } else if (theResult == CDialogs::CONTINUE_NO_SAVE)
+ return true;
+
+ return false;
+ }
+ return true;
+}
+
+//==============================================================================
+/**
+ * If the presentation is currently playing, it is stopped. The playhead is
+ * restored to the position found in m_PlaybackTime.
+ */
+void CStudioApp::PlaybackStop()
+{
+ CDoc *theDoc = m_Core->GetDoc();
+ // change it back to the original slide first before restoring the original time
+ if (m_PlaybackOriginalSlide.Valid()) {
+ if (m_PlaybackOriginalSlide != theDoc->GetActiveSlide())
+ theDoc->NotifyActiveSlideChanged(m_PlaybackOriginalSlide);
+ theDoc->SetPlayMode(PLAYMODE_STOP, m_PlaybackTime);
+ }
+ // Invalidate the playback original slide so we don't inadvertently trigger this code later.
+ m_PlaybackOriginalSlide = 0;
+}
+
+//=============================================================================
+/**
+ * Used for track wheel to do smooth tracking on mac, just scrolls the playhead.
+ */
+void CStudioApp::AdvanceTime()
+{
+ long theDeltaTime = CStudioPreferences::GetTimeAdvanceAmount();
+ long theTime =
+ (m_Core->GetDoc()->GetCurrentViewTime() + theDeltaTime) / theDeltaTime * theDeltaTime;
+ m_Core->GetDoc()->NotifyTimeChanged(theTime);
+}
+
+//=============================================================================
+/**
+ * Used for track wheel to do smooth tracking on mac, just scrolls the playhead.
+ */
+void CStudioApp::ReduceTime()
+{
+ long theDeltaTime = CStudioPreferences::GetTimeAdvanceAmount();
+ long theTime = (m_Core->GetDoc()->GetCurrentViewTime() - 1) / theDeltaTime * theDeltaTime;
+ m_Core->GetDoc()->NotifyTimeChanged(theTime);
+}
+
+//=============================================================================
+/**
+ * Used for track wheel to do smooth tracking on mac, just scrolls the playhead.
+ */
+void CStudioApp::AdvanceUltraBigTime()
+{
+ long theDeltaTime = CStudioPreferences::GetBigTimeAdvanceAmount();
+ long theTime =
+ (m_Core->GetDoc()->GetCurrentViewTime() + theDeltaTime) / theDeltaTime * theDeltaTime;
+ m_Core->GetDoc()->NotifyTimeChanged(theTime);
+}
+
+//=============================================================================
+/**
+ * Used for track wheel to do smooth tracking on mac, just scrolls the playhead.
+ */
+void CStudioApp::ReduceUltraBigTime()
+{
+ long theDeltaTime = CStudioPreferences::GetBigTimeAdvanceAmount();
+ long theTime = (m_Core->GetDoc()->GetCurrentViewTime() - 1) / theDeltaTime * theDeltaTime;
+ m_Core->GetDoc()->NotifyTimeChanged(theTime);
+}
+
+//==============================================================================
+/**
+ * If the presentation is currently playing, it is stopped. Otherwise, the
+ * presetation starts playing from its current position. Called when the user
+ * presses the Enter key.
+ */
+void CStudioApp::PlaybackToggle()
+{
+ // If the presentation is playing, stop it and leave the playhead where it is
+ if (m_Core->GetDoc()->IsPlaying())
+ PlaybackStopNoRestore();
+ // Otherwise, the presentation is stopped, so start it playing
+ else
+ PlaybackPlay();
+}
+
+CInspectableBase *CStudioApp::GetInspectableFromSelectable(Q3DStudio::SSelectedValue inSelectable)
+{
+ CInspectableBase *theInspectableBase = nullptr;
+ if (inSelectable.empty() == false) {
+ switch (inSelectable.getType()) {
+ case Q3DStudio::SelectedValueTypes::Slide:
+ theInspectableBase = new CUICDMInspectable(
+ *this, m_Core, inSelectable.getData<Q3DStudio::SSlideInstanceWrapper>().m_Instance);
+ break;
+ case Q3DStudio::SelectedValueTypes::MultipleInstances:
+ case Q3DStudio::SelectedValueTypes::Instance: {
+
+ // We need to decide whether to display SlideInspectable or UICDMInspectable
+ // We display SlideInspectable if user selects a Scene or Component where the current
+ // active slide belongs,
+ // for example when user selects the Root in Timeline Palette
+ CDoc *theDoc = m_Core->GetDoc();
+ UICDM::TInstanceHandleList theSelectedInstances =
+ theDoc->GetSelectedValue().GetSelectedInstances();
+ UICDM::CUICDMInstanceHandle theSelectedInstance;
+ if (theSelectedInstances.size() == 1)
+ theSelectedInstance = theSelectedInstances[0];
+
+ if (m_Core->GetDoc()->GetDocumentReader().IsInstance(theSelectedInstance)) {
+ CClientDataModelBridge *theBridge =
+ theDoc->GetStudioSystem()->GetClientDataModelBridge();
+ UICDM::CUICDMSlideHandle theCurrentActiveSlide = theDoc->GetActiveSlide();
+
+ // Slide, scene or component
+ if (theSelectedInstance
+ == theBridge->GetOwningComponentInstance(theCurrentActiveSlide)) {
+ CUICDMInstanceHandle theCurrentActiveSlideInstance =
+ theDoc->GetStudioSystem()->GetSlideSystem()->GetSlideInstance(
+ theCurrentActiveSlide);
+
+ if (theBridge->IsSceneInstance(theSelectedInstance))
+ theInspectableBase = new CUICDMSceneInspectable(
+ *this, m_Core, theSelectedInstance, theCurrentActiveSlideInstance);
+ else if (theBridge->IsComponentInstance(theSelectedInstance))
+ theInspectableBase = new CUICDMInspectable(
+ *this, m_Core, theSelectedInstance, theCurrentActiveSlideInstance);
+ }
+ if (theInspectableBase == nullptr) {
+ if (theBridge->IsMaterialBaseInstance(theSelectedInstance))
+ theInspectableBase =
+ new CUICDMMaterialInspectable(*this, m_Core, theSelectedInstance);
+ else
+ theInspectableBase =
+ new CUICDMInspectable(*this, m_Core, theSelectedInstance);
+ }
+ }
+ } break;
+ case Q3DStudio::SelectedValueTypes::Guide: {
+ UICDM::CUICDMGuideHandle theGuide = inSelectable.getData<UICDM::CUICDMGuideHandle>();
+ theInspectableBase = CGuideInspectable::CreateInspectable(*m_Core, theGuide);
+ } break;
+ };
+ }
+
+ return theInspectableBase;
+}
+
+void CStudioApp::RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler)
+{
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::AdvanceTime), 0, Qt::Key_Period);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::ReduceTime), 0, Qt::Key_Comma);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::AdvanceUltraBigTime),
+ Qt::ShiftModifier, Qt::Key_Greater);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::ReduceUltraBigTime),
+ Qt::ShiftModifier, Qt::Key_Less);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnToggleAutosetKeyframes), 0, Qt::Key_K);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnSaveAs),
+ Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_S);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnSave), Qt::ControlModifier,
+ Qt::Key_S);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnSaveCopy),
+ Qt::ControlModifier | Qt::AltModifier, Qt::Key_S);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnFileNew),
+ Qt::ControlModifier, Qt::Key_N);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnFileOpen),
+ Qt::ControlModifier, Qt::Key_O);
+ inShortcutHandler->RegisterKeyUpEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::PlaybackStop), 0,
+ Qt::Key_Space);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::PlaybackPlay), 0,
+ Qt::Key_Space);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::PlaybackToggle), 0,
+ Qt::Key_Return);
+
+ if (m_Views)
+ m_Views->RegisterGlobalKeyboardShortcuts(inShortcutHandler);
+}
+
+//=============================================================================
+/**
+ * Handles the Save command
+ * This will save the file, if the file has not been saved before this will
+ * do a save as operation.
+ * @return true if the file was successfully saved.
+ */
+bool CStudioApp::OnSave()
+{
+ CUICFile theCurrentDoc = m_Core->GetDoc()->GetDocumentPath();
+ if (!theCurrentDoc.IsFile()) {
+ return OnSaveAs();
+ } else if (!theCurrentDoc.CanWrite()) {
+ m_Dialogs->DisplaySavingPresentationFailed();
+ return false;
+ } else {
+ m_Core->OnSaveDocument(theCurrentDoc);
+ return true;
+ }
+}
+
+//=============================================================================
+/**
+ * Command handler for the File Save As menu option.
+ * This will prompt the user for a location to save the file out to then
+ * will perform the save.
+ * @return true if the file was successfully saved.
+ */
+bool CStudioApp::OnSaveAs()
+{
+ CUICFile theFile = m_Dialogs->GetSaveAsChoice().first;
+ if (theFile.GetPath() != "") {
+ m_Core->OnSaveDocument(theFile);
+ return true;
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * Command handler for the File Save As menu option.
+ * This will prompt the user for a location to save the file out to then
+ * save a copy, leaving the original file open in the editor.
+ * @return true if the file was successfully saved.
+ */
+bool CStudioApp::OnSaveCopy()
+{
+ CUICFile theFile = m_Dialogs->GetSaveAsChoice().first;
+ if (theFile.GetPath() != "") {
+ // Send in a "true" to teh save function to indicate this is a copy
+ m_Core->OnSaveDocument(theFile, true);
+ return true;
+ }
+ return false;
+}
+
+//=============================================================================
+/**
+ * Call to load a new document.
+ * There should not be a currently active document when this is called.
+ * @param inDocument the path to the UIP file to be loaded.
+ * @param inShowStartupDialogOnError true to show startup dialog if loading document is error
+ * @return true if loading was successful
+ */
+bool CStudioApp::OnLoadDocument(const CUICFile &inDocument, bool inShowStartupDialogOnError)
+{
+ m_Core->GetDispatch()->FireOnProgressBegin(CString::fromQString(QObject::tr("Loading...")), inDocument.GetName(),
+ CString::fromQString(QObject::tr("Loading...")));
+
+ bool theLoadResult = false;
+ int theLoadErrorParameter = -1;
+ Q3DStudio::CString theErrorText;
+ try {
+ OnLoadDocumentCatcher(inDocument);
+ m_Core->GetDispatch()->FireOnOpenDocument(inDocument, true);
+ // Loading was successful
+ theLoadResult = true;
+ } catch (CUnsupportedFileFormatException &) {
+ theErrorText = CString::fromQString(QObject::tr("The file could not be opened. It is either invalid or was made with an "
+ "old version of Studio."));
+ // We've encountered a file format that is older than the current, OR
+ // corrupt files, unsupported file formats and illegal types.
+ } catch (CInvalidFileFormatException &) {
+ theErrorText = CString::fromQString(QObject::tr("The file could not be opened. It appears to have been made with a newer "
+ "version of Studio."));
+ // Cannot support opening newer file format, the UIP or (AP ie client portion)'s version is
+ // mismatched.
+ } catch (CLoadReferencedFileException &inError) {
+ // referenced files (e.g. Data Files) failed to load
+ theErrorText.Format(L"%ls failed to load due to invalid referenced file: %ls.",
+ static_cast<const wchar_t *>(inDocument.GetName()),
+ inError.GetFilePath()); // TODO: Localize
+ const wchar_t *theDesc = inError.GetDescription();
+ if (theDesc && wcslen(theDesc) > 0) {
+ // append any description is provided
+ theErrorText += L"\n";
+ theErrorText += inError.GetDescription();
+ }
+ } catch (CIOException &) { // provide specific error message if possible
+ if (inDocument.Exists() == false)
+ theLoadErrorParameter = IDS_ERROR_LOADFILENOTEXIST;
+ qCCritical(qt3ds::INTERNAL_ERROR)
+ << "Failed to load document, IO error (file may be unreadable or nonexistent)";
+ } catch (...) {
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to load document, uknown error";
+ // We don't know exactly what went wrong during a load, but let studio 'fail gracefully'.
+ }
+
+ if (theErrorText.Length()) {
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to load document: "
+ << theErrorText.GetCharStar();
+ }
+
+ m_Core->GetDispatch()->FireOnProgressEnd();
+
+ // load fail
+ if (!theLoadResult) {
+ if (!theErrorText.IsEmpty())
+ m_Dialogs->DisplayKnownErrorDialog(theErrorText);
+ else
+ m_Dialogs->DisplayLoadingPresentationFailed(inDocument, theLoadErrorParameter);
+
+ m_Core->GetDispatch()->FireOnOpenDocument(inDocument, false);
+
+ // Show startup dialog
+#ifdef KDAB_TEMPORARILY_REMOVED
+ if (inShowStartupDialogOnError)
+ if (!ShowStartupDialog())
+ PostQuitMessage(WM_QUIT);
+#endif
+ } else {
+ m_Dialogs->ResetSettings(inDocument.GetPath());
+
+ m_subpresentations.clear();
+ m_Core->GetDoc()->LoadUIASubpresentations(m_Core->GetDoc()->GetDocumentUIAFile(),
+ m_subpresentations);
+ }
+
+ m_AuthorZoom = false;
+
+ m_Core->GetDispatch()->FireAuthorZoomChanged();
+
+ return theLoadResult;
+}
+
+
+//=============================================================================
+/**
+ *
+ */
+void CStudioApp::SaveUIAFile()
+{
+ QStringList list;
+ for (SubPresentationRecord r : m_subpresentations) {
+ list.append(r.m_type);
+ list.append(r.m_id);
+ list.append(r.m_argsOrSrc);
+ }
+ Q3DStudio::CFilePath doc(GetCore()->GetDoc()->GetDocumentPath().GetAbsolutePath());
+ uic::state::IApplication::EnsureApplicationFile(doc.GetCharStar(), list);
+}
+
+//=============================================================================
+/**
+ * Called by OnLoadDocument, to allow the error reporting to be inserted.
+ * Because of the nature of the error reporting, OnLoadDocument has to have
+ * a certain structure that limits it (C type variables, no object destructors).
+ */
+void CStudioApp::OnLoadDocumentCatcher(const CUICFile &inDocument)
+{
+ {
+ CDispatchDataModelNotificationScope __scope(*m_Core->GetDispatch());
+ m_Core->GetDoc()->CloseDocument();
+ m_Core->GetDoc()->LoadDocument(inDocument);
+ }
+
+ // Make sure the client scene is resized properly
+ if (m_Views)
+ m_Views->RecheckMainframeSizingMode();
+}
+
+void CStudioApp::OnFileOpen()
+{
+ if (PerformSavePrompt()) {
+ CUICFile theFile = m_Dialogs->GetFileOpenChoice();
+ if (theFile.GetPath() != "")
+ OnLoadDocument(theFile);
+ }
+}
+using namespace std;
+
+void CStudioApp::OnFileNew()
+{
+ if (PerformSavePrompt()) {
+ pair<CUICFile, bool> theFile = m_Dialogs->GetNewDocumentChoice();
+ if (theFile.first.GetPath() != "")
+ m_Core->OnNewDocument(theFile.first, theFile.second);
+ }
+}
+
+bool CStudioApp::IsAuthorZoom()
+{
+ return m_AuthorZoom;
+}
+
+void CStudioApp::SetAuthorZoom(bool inZoom)
+{
+ if (m_AuthorZoom != inZoom) {
+ m_AuthorZoom = inZoom;
+ m_Core->GetDispatch()->FireAuthorZoomChanged();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// These commands come over the dispatch from inside the core. The core doesn't
+// have access to the CMsgRouter at the moment, so this relays the message.
+void CStudioApp::OnAsynchronousCommand(CCmd *inCmd)
+{
+ CMsgRouter::GetInstance()->SendCommand(inCmd, m_Core);
+}
+
+void CStudioApp::OnDisplayAppStatus(Q3DStudio::CString &inStatusMsg)
+{
+ // Do nothing, it was used to show this in the status bar
+}
+
+void CStudioApp::OnProgressBegin(const Q3DStudio::CString &inActionText,
+ const Q3DStudio::CString &inFileName,
+ const Q3DStudio::CString &inWindowTitle)
+{
+ m_Dialogs->DisplayProgressScreen(inActionText, inFileName, inWindowTitle);
+}
+
+void CStudioApp::OnProgressEnd()
+{
+ m_Dialogs->DestroyProgressScreen();
+}
+
+void CStudioApp::OnAssetDeleteFail()
+{
+ m_Dialogs->DisplayAssetDeleteFailed();
+}
+
+void CStudioApp::OnPasteFail()
+{
+ m_Dialogs->DisplayPasteFailed();
+}
+
+void CStudioApp::OnBuildconfigurationFileParseFail(const Q3DStudio::CString &inMessage)
+{
+ m_Dialogs->DisplayMessageBox(::LoadResourceString(IDS_BUILDCONFIGS_ERROR_TITLE), inMessage,
+ CUICMessageBox::ICON_ERROR, false);
+}
+
+void CStudioApp::OnSaveFail(bool inKnownError)
+{
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to save project: "
+ << (inKnownError ? "KnownError" : "UnknownError");
+ if (inKnownError) {
+ m_Dialogs->DisplaySavingPresentationFailed();
+ } else {
+ m_Dialogs->DisplayKnownErrorDialog(::LoadResourceString(IDS_SAVE_UNKNOWN_ERROR));
+ }
+}
+
+void CStudioApp::OnProjectVariableFail(const Q3DStudio::CString &inMessage)
+{
+ m_Dialogs->DisplayEnvironmentVariablesError(inMessage);
+}
+
+void CStudioApp::OnErrorFail(const Q3DStudio::CString &inText)
+{
+ qCCritical(qt3ds::INTERNAL_ERROR) << inText.GetCharStar();
+ m_Dialogs->DisplayMessageBox(::LoadResourceString(IDS_PROJNAME), inText,
+ CUICMessageBox::ICON_ERROR, false);
+}
+
+void CStudioApp::OnRefreshResourceFail(const Q3DStudio::CString &inResourceName,
+ const Q3DStudio::CString &inDescription)
+{
+ qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to refresh resource: "
+ << inResourceName.GetCharStar();
+ qCCritical(qt3ds::INTERNAL_ERROR) << inDescription.GetCharStar();
+ m_Dialogs->DisplayRefreshResourceFailed(inResourceName, inDescription);
+}
+
+void CStudioApp::OnNewPresentation()
+{
+ m_Core->GetDoc()->GetStudioSystem()->GetAnimationSystem()->SetAutoKeyframe(
+ CStudioPreferences::IsAutosetKeyframesOn());
+ qCInfo(qt3ds::TRACE_INFO) << "New Presentation: "
+ << m_Core->GetDoc()->GetDocumentPath().GetAbsolutePath().GetCharStar();
+}
+
+void CStudioApp::OnPresentationModifiedExternally()
+{
+ int theUserChoice = m_Dialogs->DisplayChoiceBox(
+ ::LoadResourceString(IDS_TITLE_WARNING),
+ ::LoadResourceString(IDS_PRESENTATION_MODIFIED_EXTERNALLY), CUICMessageBox::ICON_WARNING);
+ if (theUserChoice == IDYES) {
+ CUICFile theCurrentDoc = m_Core->GetDoc()->GetDocumentPath();
+ OnLoadDocument(theCurrentDoc);
+ }
+}
diff --git a/src/Authoring/Studio/_Win/Application/StudioApp.h b/src/Authoring/Studio/_Win/Application/StudioApp.h
new file mode 100644
index 00000000..caea5158
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/StudioApp.h
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STUDIO_APP_H
+#define INCLUDED_STUDIO_APP_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "CmdLineParser.h"
+#include "StudioObjectTypes.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include <minmax.h>
+#include <gdiplus.h>
+#endif
+#include "DispatchListeners.h"
+#include "UICDMHandles.h"
+
+#include <QApplication>
+
+namespace Q3DStudio {
+class IInternalDirectoryWatchingSystem;
+class IDirectoryWatchingSystem;
+class ITickTock;
+class IStudioRenderer;
+struct SSelectedValue;
+};
+
+namespace UICDM {
+class ISignalConnection;
+};
+
+struct StudioManipulationModes
+{
+ enum Enum {
+ Local,
+ Global,
+ };
+};
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CCore;
+class CDialogs;
+class CSplashView;
+class CInspectableBase;
+class CDirectoryWatchingSystemWrapper;
+class CHotKeys;
+class CViews;
+class CMainFrame;
+enum EStudioObjectType;
+struct SubPresentationRecord;
+
+class CStudioApp : public CCoreAsynchronousEventListener,
+ public CAppStatusListener,
+ public CFailListener,
+ public CPresentationChangeListener // to setup auto set keyframes
+{
+public:
+ CStudioApp();
+ virtual ~CStudioApp();
+
+ // Overrides
+public:
+ virtual BOOL InitInstance(int argc, char *argv[]);
+ virtual int ExitInstance();
+ virtual int Run();
+#ifdef KDAB_TEMPORARILY_REMOVED
+ virtual UINT GetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault);
+ virtual BOOL WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue);
+ virtual ::CString GetProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry,
+ LPCTSTR lpszDefault = nullptr);
+ virtual BOOL WriteProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue);
+#endif
+
+ void OnAppAbout();
+
+public:
+ void PerformShutdown();
+#ifdef KDAB_TEMPORARILY_REMOVED
+ static void StudioUnhandledCrashHandler(EXCEPTION_POINTERS *pExPtrs);
+#endif
+ Q3DStudio::IDirectoryWatchingSystem &GetDirectoryWatchingSystem();
+ void SetupTimer(long inMessageId, QWidget *inWnd);
+ Q3DStudio::ITickTock &GetTickTock();
+ Q3DStudio::IStudioRenderer &GetRenderer();
+ void ClearGuides();
+
+protected:
+ int RunApplication();
+ int BlankRunApplication();
+ int RunCmdLineTests(const Q3DStudio::CString &inTestArgs);
+ int RunSystemTests(const Q3DStudio::CString &inTestArgs);
+ int OpenAndRunApplication(const Q3DStudio::CString &inFilename);
+ void InitCore();
+ void InitHelpSystem();
+ bool ShowStartupDialog();
+ bool HandleWelcomeRes(int res, bool recursive);
+
+ CCore *m_Core;
+ CSplashView *m_SplashPalette; ///< Startup splash palette
+ QString m_OldHelpFilePath; ///< Stores a pointer to the old
+ CCmdLineParser m_CmdLineParser; ///< Stores and returns execution modes
+ int m_UnitTestResults; ///< 0 on success; 1 on failure
+ bool m_IsSilent; ///< true indicates Studio running in silent mode (no GUI)
+ CViews *m_Views;
+ long m_ToolMode;
+ StudioManipulationModes::Enum
+ m_ManipulationMode; ///< Controls what space the tras,rot,and scale manipulations work in.
+ long m_SelectMode;
+ CDialogs *m_Dialogs;
+ long m_PlaybackTime; ///< Stores the playhead's starting position so that it can be restored
+ ///after playing the presentation for a little while
+ UICDM::CUICDMSlideHandle
+ m_PlaybackOriginalSlide; ///< Stores the current slide handle before playback started.
+
+ std::shared_ptr<Q3DStudio::ITickTock> m_TickTock;
+ std::shared_ptr<Q3DStudio::IDirectoryWatchingSystem> m_DirectoryWatchingSystem;
+ std::shared_ptr<UICDM::ISignalConnection> m_DirectoryWatcherTicker;
+ std::shared_ptr<Q3DStudio::IStudioRenderer> m_Renderer;
+ bool m_AuthorZoom;
+
+private:
+#ifdef KDAB_TEMPORARILY_REMOVED
+ Gdiplus::GdiplusStartupInput m_gdiplusStartupInput;
+ ULONG_PTR m_pGdiToken;
+#endif
+
+ bool m_welcomeShownThisSession;
+ // are we are launching welcome screen again due to
+ // user canceling file dialog?
+ bool m_goStraightToWelcomeFileDialog;
+ int m_tutorialPage;
+public:
+ CMainFrame* m_pMainWnd;
+
+ CCore *GetCore();
+ CViews *GetViews();
+ CDialogs *GetDialogs();
+ long GetToolMode();
+ void SetToolMode(long inToolMode);
+ long GetSelectMode();
+ void SetSelectMode(long inSelectMode);
+
+ StudioManipulationModes::Enum GetMinpulationMode() const;
+ void SetMinpulationMode(StudioManipulationModes::Enum inManipulationMode);
+
+ bool CanUndo();
+ bool CanRedo();
+ void OnCopy();
+ bool CanCopy();
+ Q3DStudio::CString GetCopyType();
+ void OnCut();
+ bool CanCut();
+ void OnPaste();
+ bool CanPaste();
+ Q3DStudio::CString GetPasteType();
+ void SetSelectedObjectTimebarColor();
+ bool CanChangeTimebarColor();
+ void HandleSetChangedKeys();
+ void DeleteSelectedKeys();
+ void HandleDuplicateCommand();
+ bool CanDuplicateObject();
+ void OnToggleAutosetKeyframes();
+ void SetAutosetKeyframes(bool inFlag);
+ void PlaybackPlay();
+ void PlaybackStopNoRestore();
+ void PlaybackRewind();
+ void OnRevert();
+ bool CanRevert();
+ void OnFileOpenRecent(const CUICFile &inDocument);
+ bool PerformSavePrompt();
+ void PlaybackStop();
+ void AdvanceTime();
+ void ReduceTime();
+ void AdvanceUltraBigTime();
+ void ReduceUltraBigTime();
+ void PlaybackToggle();
+ CInspectableBase *GetInspectableFromSelectable(Q3DStudio::SSelectedValue inSelectable);
+ void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler);
+ bool OnSave();
+ bool OnSaveAs();
+ bool OnSaveCopy();
+ bool OnLoadDocument(const CUICFile &inDocument, bool inShowStartupDialogOnError = true);
+ void OnLoadDocumentCatcher(const CUICFile &inLocation);
+ void OnFileOpen();
+ void OnFileNew();
+ bool IsAuthorZoom();
+ void SetAuthorZoom(bool inZoom);
+
+ // CCoreAsynchronousEventListener
+ void OnAsynchronousCommand(CCmd *inCmd) override;
+
+ // CAppStatusListener
+ void OnDisplayAppStatus(Q3DStudio::CString &inStatusMsg) override;
+ void OnProgressBegin(const Q3DStudio::CString &inActionText,
+ const Q3DStudio::CString &inFileName,
+ const Q3DStudio::CString &inWindowTitle) override;
+ void OnProgressEnd() override;
+
+ // CFailListener
+ void OnAssetDeleteFail() override;
+ void OnPasteFail() override;
+ void OnBuildconfigurationFileParseFail(const Q3DStudio::CString &inMessage) override;
+ void OnSaveFail(bool inKnownError) override;
+ void OnProjectVariableFail(const Q3DStudio::CString &inMessage) override;
+ void OnErrorFail(const Q3DStudio::CString &inText) override;
+ void OnRefreshResourceFail(const Q3DStudio::CString &inResourceName,
+ const Q3DStudio::CString &inDescription) override;
+
+ // CPresentationChangeListener
+ void OnNewPresentation() override;
+ void OnPresentationModifiedExternally() override;
+
+ Q3DStudio::CString m_pszHelpFilePath;
+
+ QVector<SubPresentationRecord> m_subpresentations;
+ void SaveUIAFile();
+};
+
+extern CStudioApp g_StudioApp;
+
+#endif // INCLUDED_STUDIO_APP_H
diff --git a/src/Authoring/Studio/_Win/Application/StudioColors.h b/src/Authoring/Studio/_Win/Application/StudioColors.h
new file mode 100644
index 00000000..776047a5
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/StudioColors.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 Anark Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STUDIOCOLORS_H
+#define INCLUDED_STUDIOCOLORS_H
+
+#pragma once
+
+//==============================================================================
+// Studio colors
+//==============================================================================
+
+const COLORREF STUDIO_MATTE_COLOR = RGB(119, 122, 125); // GetSysColor( COLOR_APPWORKSPACE );
+const COLORREF MENU_IMAGELIST_BACKCOLOR = RGB(255, 0, 255); // RGB( 255, 128, 0 );
+
+//==============================================================================
+// TimeBar colors
+//==============================================================================
+
+// TimeBar pen colors
+
+const COLORREF TIMEBAR_PEN_COLOR_INNER = RGB(254, 254, 254);
+const COLORREF TIMEBAR_PEN_COLOR_INACTIVE = RGB(132, 130, 132);
+const COLORREF TIMEBAR_PEN_COLOR_ACTIVE = RGB(0, 0, 0);
+
+// TimeBar shadow colors
+
+const COLORREF TIMEBAR_INACTIVE_SHADOW_COLOR = RGB(0xC4, 0xC4, 0xC4);
+const COLORREF TIMEBAR_ACTIVE_SHADOW_COLOR = RGB(0x84, 0x84, 0x84);
+
+// TimeBar comment colors
+
+const COLORREF TIMEBAR_COMMENT_ACTIVE_TC = RGB(0x00, 0x00, 0x00);
+const COLORREF TIMEBAR_COMMENT_INACTIVE_TC = RGB(0x72, 0x72, 0x72);
+
+const COLORREF COLOR_TIMEBAR_DISABLED = RGB(207, 207, 207);
+const COLORREF COLOR_TIMEBAR_BEHAVIOR =
+ RGB(148, 189, 150); // RGB( 92, 164, 131 );//RGB( 243, 243, 243 );
+const COLORREF COLOR_TIMEBAR_MATERIAL =
+ RGB(194, 155, 181); // RGB( 190, 184, 152 ); //RGB( 239, 230, 210 );
+const COLORREF COLOR_TIMEBAR_IMAGE =
+ RGB(194, 155, 181); // RGB( 190, 184, 152 ); //RGB( 198, 225, 199 );
+const COLORREF COLOR_TIMEBAR_LOCKED = RGB(228, 228, 228);
+
+const COLORREF TIMEBAR_COLOR_TRANSPARENT = RGB(255, 0, 255);
+
+// A constant to represent color for inner white rectangle of center bar
+const COLORREF COLOR_INNER_BAR_RECTANGLE = RGB(253, 253, 254);
+// Default timebar fill color
+const COLORREF COLOR_TIMEBAR_DEFAULT_FILL = RGB(
+ 163, 178, 227); // RGB( 174, 183, 210 ); //RGB( 148, 166, 189 ); //RGB( 211, 226, 240 );
+
+// Selected time bar colors
+
+const COLORREF COLOR_TIMEBAR_SELECTED = RGB(75, 75, 75); // RGB( 14, 49, 98 );
+const COLORREF COLOR_TIMEBAR_SELECTED_TEXT = RGB(255, 255, 255);
+const COLORREF COLOR_TIMEBAR_SELECTED_BEHAVIOR = RGB(174, 216, 176);
+const COLORREF COLOR_TIMEBAR_SELECTED_HIGHLIGHT = RGB(27, 73, 136);
+
+// const COLORREF COLOR_SELECTED_TIMEBAR_3DOBJECT = RGB( 190, 191, 202
+// );
+
+const COLORREF COLOR_TIMEBAR_HIGHLIGHT = RGB(190, 191, 202);
+const COLORREF COLOR_TIMEBAR_HIGHLIGHT_GROUP = RGB(174, 216, 176);
+
+const COLORREF COLOR_PLAYHEADSCRUBTIME = RGB(0, 85, 0);
+
+//==============================================================================
+// Timeline colors
+//==============================================================================
+
+const BOOL INVERT_TIMELINE_TEXT_COLOR = TRUE;
+
+const COLORREF COLOR_SELECTEDTEXT = RGB(255, 255, 255);
+const COLORREF COLOR_SELECTEDTEXTBKGRND = RGB(14, 49, 98);
+const COLORREF COLOR_DRAGDROPTARGETTEXT = RGB(255, 255, 255);
+const COLORREF COLOR_DRAGDROPTARGETBKGRND = RGB(24, 98, 198);
+
+const COLORREF COLOR_SHADOW = RGB(165, 162, 161); // RGB( 132, 130, 132 );
+
+const COLORREF COLOR_PLAYHEADLINE = RGB(0xDD, 0x04, 0x05);
+const COLORREF COLOR_BACKGRND =
+ GetSysColor(COLOR_3DFACE); // RGB( 206, 203, 198 ); //RGB( 0xE7, 0xE7, 0xE7 );
+const COLORREF COLOR_SELECTED = RGB(255, 255, 255);
+const COLORREF COLOR_DEFAULTOBJECTS = RGB(206, 203, 198); // RGB( 0xE7, 0xE7, 0xE7 );
+const COLORREF COLOR_3DOBJECTS = RGB(206, 203, 198); // RGB( 0xC7, 0xD4, 0xE1 );
+const COLORREF COLOR_DEFAULTOBJECTHIGHLIGHT = RGB(222, 223, 222); // RGB( 255, 255, 255 );
+const COLORREF COLOR_DRAGHIGHLIGHT = RGB(255, 255, 255);
+const COLORREF COLOR_INSERTMARK = RGB(0x00, 0x00, 0x00);
+const COLORREF COLOR_TIMELINEINSERTMARK = RGB(0x00, 0x00, 0xFF);
+const COLORREF COLOR_TEXTCOLOR = RGB(0x00, 0x00, 0x00);
+const COLORREF COLOR_CONTAINERTEXTCOLOR = RGB(80, 80, 140);
+const COLORREF COLOR_LOCKEDTEXTCOLOR = RGB(0x80, 0x80, 0x80);
+const COLORREF COLOR_INDEPENDENTOBJECT = RGB(0x80, 0x80, 0x80);
+const COLORREF COLOR_SPLITLINE = RGB(0x00, 0x00, 0x7F);
+const COLORREF COLOR_SEPARATORLINE = RGB(0x00, 0x00, 0x20);
+const COLORREF COLOR_LIGHTMODEL = RGB(206, 203, 198); // RGB( 198, 211, 224 );
+const COLORREF COLOR_GROUP =
+ RGB(206, 203, 198); // RGB( 198, 211, 224 ); //RGB( 199, 220, 193 );
+const COLORREF COLOR_PROPERTY = RGB(228, 225, 219); // RGB( 241, 241, 241 );
+const COLORREF COLOR_CHANNEL = RGB(228, 225, 219); // RGB( 241, 241, 241 );
+const COLORREF COLOR_CONTAINER =
+ RGB(228, 225, 219); // RGB( 206, 203, 198 ); //RGB( 231, 231, 231 );
+const COLORREF COLOR_MATERIAL = RGB(210, 210, 210); // RGB( 170, 224, 170 );
+const COLORREF COLOR_CONTAINERHIGHLIGHT = RGB(193, 180, 180);
+const COLORREF COLOR_BEHAVIOR = RGB(199, 220, 193);
+const COLORREF COLOR_BEHAVIORHIGHLIGHT = RGB(255, 255, 255);
+const COLORREF COLOR_IMGLISTTRANSPARENT = RGB(0xFF, 0x00, 0xFF);
+const COLORREF COLOR_TIMEMEASURE = GetSysColor(COLOR_3DFACE); // RGB( 170, 166, 160 );
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.cpp b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.cpp
new file mode 100644
index 00000000..e3e25fa1
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.cpp
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "StudioDefs.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SubPresentationsDlg.h"
+#include "ui_SubPresentationsDlg.h"
+#include "ProductInfo.h"
+#include "HotKeys.h"
+#include "Preferences.h"
+#include "StudioPreferences.h"
+
+#include <QtGui/qevent.h>
+#include <QtGui/qpainter.h>
+#include <QtCore/qtimer.h>
+#include <QtWidgets/qfiledialog.h>
+
+CSubPresentationsDlg::CSubPresentationsDlg(
+ const QString &directory,
+ const QVector<SubPresentationRecord> &subpresentations,
+ QWidget *parent)
+ : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint)
+ , m_directory(directory)
+ , m_records(subpresentations)
+ , m_ui(new Ui::SubPresentationsDlg)
+{
+ m_ui->setupUi(this);
+
+ connect(m_ui->deleteButton, &QPushButton::clicked, this,
+ &CSubPresentationsDlg::OnDeletePresentation);
+ connect(m_ui->pushButtonNew, &QPushButton::clicked, this,
+ &CSubPresentationsDlg::OnNewPresentation);
+ connect(m_ui->pushButtonBrowse, &QPushButton::clicked, this,
+ &CSubPresentationsDlg::OnBrowsePresentation);
+ connect(m_ui->comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ this, &CSubPresentationsDlg::OnSelectPresentation);
+ connect(m_ui->lineEditId, &QLineEdit::textEdited, this, &CSubPresentationsDlg::OnIdChanged);
+
+ OnInitDialog();
+}
+
+CSubPresentationsDlg::~CSubPresentationsDlg()
+{
+ delete m_ui;
+}
+
+QVector<SubPresentationRecord> CSubPresentationsDlg::subpresentations() const
+{
+ return m_records;
+}
+
+void CSubPresentationsDlg::OnInitDialog()
+{
+ current = -1;
+ if (m_records.size() > 0) {
+ for (SubPresentationRecord rec : m_records)
+ m_ui->comboBox->addItem(rec.m_id);
+ current = 0;
+ m_ui->lineEditId->setText(m_records[0].m_id);
+ m_ui->lineEditPreview->setText(m_records[0].m_argsOrSrc);
+ }
+ m_ui->lineEditPreview->setReadOnly(true);
+ m_ui->buttonBox->setFocusPolicy(Qt::NoFocus);
+}
+
+void CSubPresentationsDlg::OnSelectPresentation(int selectionIndex)
+{
+ if (selectionIndex >= 0 && selectionIndex < m_records.size()) {
+ current = selectionIndex;
+ m_ui->lineEditId->setText(m_records[current].m_id);
+ m_ui->lineEditPreview->setText(m_records[current].m_argsOrSrc);
+ } else {
+ m_ui->lineEditId->setText(QString());
+ m_ui->lineEditPreview->setText(QString());
+ }
+}
+
+void CSubPresentationsDlg::OnDeletePresentation()
+{
+ if (current >= 0 && current < m_records.size()) {
+ m_records.remove(current);
+ m_ui->comboBox->removeItem(current);
+ current = qMax(current - 1, 0);
+ if (m_records.size() == 0)
+ current = -1;
+ OnSelectPresentation(current);
+ }
+}
+
+void CSubPresentationsDlg::OnNewPresentation()
+{
+ int index = m_records.size();
+ m_records.push_back(
+ SubPresentationRecord(QStringLiteral("presentation-qml"),
+ QStringLiteral("presentation-id"), QString()));
+ m_ui->comboBox->addItem(QStringLiteral("presentation-id"));
+ m_ui->comboBox->setCurrentIndex(index);
+ OnSelectPresentation(index);
+}
+
+void CSubPresentationsDlg::OnBrowsePresentation()
+{
+ const QString file = QDir::toNativeSeparators(
+ QFileDialog::getOpenFileName(nullptr, nullptr, m_directory,
+ QStringLiteral("*.qml; *.uip")));
+ QString shortFile = file;
+ int subdir = file.indexOf(m_directory);
+ if (subdir >= 0)
+ shortFile.remove(subdir, m_directory.size() + 1);
+
+ QFileInfo fileInfo(file);
+ if (fileInfo.exists()) {
+ if (fileInfo.suffix() == QStringLiteral("qml"))
+ m_records[current].m_type = QStringLiteral("presentation-qml");
+ else
+ if (fileInfo.suffix() == QStringLiteral("uip"))
+ m_records[current].m_type = QStringLiteral("presentation");
+
+ m_records[current].m_argsOrSrc = shortFile;
+ m_ui->lineEditPreview->setText(shortFile);
+ }
+}
+
+void CSubPresentationsDlg::OnIdChanged(const QString &text)
+{
+ m_records[current].m_id = text;
+ m_ui->comboBox->setItemText(current, text);
+}
+
+void CSubPresentationsDlg::on_buttonBox_accepted()
+{
+ QDialog::accept();
+}
+
+void CSubPresentationsDlg::on_buttonBox_rejected()
+{
+ QDialog::reject();
+}
diff --git a/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.h b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.h
new file mode 100644
index 00000000..75828c4e
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef SUBPRESENTATIONSDLG_H
+#define SUBPRESENTATIONSDLG_H
+
+#include <QtWidgets/qdialog.h>
+
+#include "UICString.h"
+#include "Doc.h"
+
+#ifdef QT_NAMESPACE
+using namespace QT_NAMESPACE;
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class SubPresentationsDlg;
+}
+QT_END_NAMESPACE
+
+class CSubPresentationsDlg : public QDialog
+{
+ Q_OBJECT
+public:
+ CSubPresentationsDlg(const QString &directory,
+ const QVector<SubPresentationRecord> &subpresentations,
+ QWidget* parent = nullptr);
+ ~CSubPresentationsDlg();
+
+ // Implementation
+protected:
+
+ void OnInitDialog();
+
+public:
+
+ QVector<SubPresentationRecord> subpresentations() const;
+
+ void OnDeletePresentation();
+ void OnNewPresentation();
+ void OnBrowsePresentation();
+ void OnSelectPresentation(int selectionIndex);
+ void OnIdChanged(const QString &text);
+
+private Q_SLOTS:
+ void on_buttonBox_accepted();
+ void on_buttonBox_rejected();
+
+private:
+ QString m_directory;
+ QVector<SubPresentationRecord> m_records;
+ Ui::SubPresentationsDlg *m_ui;
+ int current;
+};
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.ui b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.ui
new file mode 100644
index 00000000..db673925
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.ui
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SubPresentationsDlg</class>
+ <widget class="QDialog" name="SubPresentationsDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>512</width>
+ <height>169</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Sub-presentations</string>
+ </property>
+ <widget class="QWidget" name="horizontalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>130</y>
+ <width>491</width>
+ <height>31</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="focusPolicy">
+ <enum>Qt::NoFocus</enum>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="horizontalLayoutWidget_2">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>491</width>
+ <height>111</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Sub-presentation</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Presentation Id</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Filename</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QComboBox" name="comboBox"/>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEditId">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Edit the name of the sub-presentation&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEditPreview">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QPushButton" name="deleteButton">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Delete currently selected sub-presentation&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButtonNew">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add new sub-presentation&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButtonBrowse">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Browse for the sub-presentation source&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/Authoring/Studio/_Win/Application/TextLink.cpp b/src/Authoring/Studio/_Win/Application/TextLink.cpp
new file mode 100644
index 00000000..a68aaea8
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/TextLink.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+#ifdef _DEBUG
+//#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "TextLink.h"
+#include "Resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextLink class
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CTextLink::CTextLink()
+ : CBaseLink()
+{
+ // Set default colors
+ m_ColorText = CStudioPreferences::GetNormalColor();
+ m_ColorBackground = CStudioPreferences::GetBaseColor();
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CTextLink::~CTextLink()
+{
+}
+
+//==============================================================================
+/**
+ * SetColor: Sets the text color and background color
+ *
+ * @param inText Text color for the control.
+ * @param inBackground Background color for the control.
+ */
+//==============================================================================
+void CTextLink::SetColor(COLORREF inText, COLORREF inBackground)
+{
+ m_ColorText = inText;
+ m_ColorBackground = inBackground;
+}
+
+//==============================================================================
+/**
+ * ShowLink: Shows the link.
+ *
+ * @param None
+ */
+//==============================================================================
+void CTextLink::ShowLink()
+{
+ if (IsWindow(m_hWnd)) {
+ ShowTextLink(m_ColorText, m_ColorBackground, DT_VCENTER | DT_SINGLELINE, m_bCapture);
+ }
+}
diff --git a/src/Authoring/Studio/_Win/Application/TextLink.h b/src/Authoring/Studio/_Win/Application/TextLink.h
new file mode 100644
index 00000000..85f5fedf
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/TextLink.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef _TEXTLINK_H_
+#define _TEXTLINK_H_
+
+#include "BaseLink.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextLink window
+
+class CTextLink : public CBaseLink
+{
+ // Construction
+public:
+ CTextLink();
+
+ // Attributes
+public:
+ // Operations
+public:
+ virtual void SetColor(COLORREF inText, COLORREF inBackground);
+
+protected:
+ COLORREF m_ColorText;
+ COLORREF m_ColorBackground;
+
+ virtual void ShowLink();
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTextLink)
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ virtual ~CTextLink();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CTextLink)
+ //}}AFX_MSG
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Application/WebLink.cpp b/src/Authoring/Studio/_Win/Application/WebLink.cpp
new file mode 100644
index 00000000..258bdffb
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/WebLink.cpp
@@ -0,0 +1,440 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+#ifdef _DEBUG
+//#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "WebLink.h"
+#include "Resource.h"
+#include "BCMenu.h"
+#include "StudioColors.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CWebLink class
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CWebLink::CWebLink()
+ : CBaseLink()
+{
+ // Set default link colors
+ m_ColorLink = CStudioPreferences::GetMasterColor(); // green
+ m_ColorHighlight = RGB(0xFF, 0x00, 0x00); // red
+ m_ColorVisited = RGB(0x7F, 0x00, 0x7F); // purple
+ m_ColorBackground = CStudioPreferences::GetDarkBaseColor();
+
+ m_bVisited = FALSE;
+
+ m_URL.Empty();
+
+ m_Bitmap = nullptr;
+
+ m_bPopup = FALSE;
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CWebLink::~CWebLink()
+{
+}
+
+//==============================================================================
+// Message Map
+//==============================================================================
+
+BEGIN_MESSAGE_MAP(CWebLink, CWnd)
+//{{AFX_MSG_MAP(CWebLink)
+ON_WM_PAINT()
+ON_WM_SETCURSOR()
+ON_WM_LBUTTONDOWN()
+ON_WM_MOUSEMOVE()
+ON_WM_CONTEXTMENU()
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * SetURL: Sets the URL for the control.
+ *
+ * @param inURL URL to point the default browser to when the control is clicked.
+ */
+//==============================================================================
+void CWebLink::SetURL(CString inURL)
+{
+ m_URL = inURL;
+}
+
+//==============================================================================
+/**
+ * SetImage: Sets an bitmap image for the control.
+ *
+ * @param inResBmp BITMAP resource for the image to load.
+ * @param inAutoSizeFlag TRUE if the control should be resized to the image size.
+ */
+//==============================================================================
+void CWebLink::SetImage(UINT inResBmp, bool inAutoSizeFlag)
+{
+ HBITMAP theBitmap = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inResBmp),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ if (theBitmap != nullptr) {
+ this->SetImage(theBitmap, inAutoSizeFlag);
+ }
+}
+
+//==============================================================================
+/**
+ * SetImage: Sets an bitmap image for the control.
+ *
+ * @param inBitmap HBITMAP handle of the loaded bitmap.
+ * @param inAutoSizeFlag TRUE if the control should be resized to the image size.
+ */
+//==============================================================================
+void CWebLink::SetImage(HBITMAP inBitmap, bool inAutoSizeFlag)
+{
+ m_Bitmap = inBitmap;
+
+ if (inAutoSizeFlag && m_Bitmap != nullptr) {
+ // Resize this control based on the size of the bitmap.
+ BITMAP theBitmapStruct;
+ int theWidth, theHeight;
+
+ GetObject(m_Bitmap, sizeof(BITMAP), &theBitmapStruct);
+ theWidth = theBitmapStruct.bmWidth;
+ theHeight = theBitmapStruct.bmHeight;
+
+ SetWindowPos(nullptr, 0, 0, theWidth, theHeight, SWP_NOZORDER | SWP_NOMOVE);
+ }
+
+ this->ShowLink();
+}
+
+//==============================================================================
+/**
+ * SetText: Sets the text for the control.
+ *
+ * @param inText Text for the control.
+ */
+//==============================================================================
+void CWebLink::SetText(CString inText)
+{
+ SetWindowText(inText);
+ m_Bitmap = nullptr;
+ this->ShowLink();
+}
+
+COLORREF CWebLink::GetColor()
+{
+ if (m_bCapture) {
+ return m_ColorHighlight;
+ } else {
+ if (m_bVisited)
+ return m_ColorVisited;
+ else
+ return m_ColorLink;
+ }
+}
+
+//==============================================================================
+/**
+ * ShowLink: Shows the link.
+ *
+ * @param None
+ */
+//==============================================================================
+void CWebLink::ShowLink()
+{
+ if (IsWindow(m_hWnd)) {
+ // Is the link represented by an image?
+ if (m_Bitmap != nullptr) {
+ ShowBitmapLink();
+ } else {
+ ShowTextLink(GetColor(), m_ColorBackground, DT_WORDBREAK | SS_LEFT, true);
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * ShowLink: Shows the bitmap link.
+ *
+ * @param None
+ */
+//==============================================================================
+void CWebLink::ShowBitmapLink()
+{
+ if (IsWindow(m_hWnd)) {
+ CRect theRect;
+ CDC *theDC;
+ CDC theMemDC;
+
+ BITMAP theBitmapStruct;
+ long theWidth, theHeight;
+ CBrush theBrush;
+
+ theDC = GetDC();
+ theMemDC.CreateCompatibleDC(theDC);
+ CBitmap *theBitmap = CBitmap::FromHandle(m_Bitmap);
+
+ CBitmap *theOldBmp = (CBitmap *)theMemDC.SelectObject(theBitmap);
+
+ GetObject(m_Bitmap, sizeof(BITMAP), &theBitmapStruct);
+ theWidth = theBitmapStruct.bmWidth;
+ theHeight = theBitmapStruct.bmHeight;
+
+ theDC->BitBlt(0, 0, theWidth, theHeight, &theMemDC, 0, 0, SRCCOPY);
+
+ COLORREF theColor = GetColor();
+ if (theColor == m_ColorHighlight || theColor == m_ColorVisited) {
+ // Draw a highlight frame
+ GetClientRect(&theRect);
+
+ theBrush.CreateSolidBrush(theColor);
+ theDC->FrameRect(&theRect, &theBrush);
+ theBrush.DeleteObject();
+ }
+
+ theMemDC.SelectObject(theOldBmp);
+
+ theMemDC.DeleteDC();
+ ReleaseDC(theDC);
+ }
+}
+
+//==============================================================================
+/**
+ * JumpLink: Jumps to the link URL.
+ *
+ * @param None
+ */
+//==============================================================================
+void CWebLink::JumpLink()
+{
+ CString theWebLink;
+
+ GetWindowText(theWebLink);
+
+ if (!m_URL.IsEmpty())
+ theWebLink = m_URL;
+
+ if (!theWebLink.IsEmpty()) {
+ this->OpenURL(theWebLink);
+ }
+}
+
+//==============================================================================
+/**
+ * OpenURL: Opens the specified URL with the default browser.
+ *
+ * @param inURL URL to open with the browser.
+ */
+//==============================================================================
+void CWebLink::OpenURL(CString inURL)
+{
+ HCURSOR thePrevCursor;
+
+ thePrevCursor = SetCursor(LoadCursor(nullptr, IDC_APPSTARTING));
+ ShellExecute(GetSafeHwnd(), L"open", inURL, nullptr, nullptr, SW_SHOWNORMAL);
+ SetCursor(thePrevCursor);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CWebLink message handlers
+
+//==============================================================================
+/**
+ * OnSetCursor
+ *
+ * Handle the WM_SETCURSOR message.
+ *
+ * @param inWnd Pointer to the parent CWnd object.
+ * @param inHitTest Specifies the hit-test area code. The hit test determines the
+ *cursor�s location.
+ * @param inMessage Specifies the mouse message number.
+ */
+//==============================================================================
+BOOL CWebLink::OnSetCursor(CWnd *inWnd, UINT inHitTest, UINT inMessage)
+{
+ UNREFERENCED_PARAMETER(inWnd);
+ UNREFERENCED_PARAMETER(inHitTest);
+ UNREFERENCED_PARAMETER(inMessage);
+
+ if (m_bPopup) {
+ SetCursor(LoadCursor(nullptr, IDC_ARROW));
+ } else {
+ SetCursor(LoadCursor(nullptr, IDC_HAND));
+ }
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * OnLButtonDown
+ *
+ * Windows callback handler for the WM_LBUTTONDOWN message
+ *
+ * @param inFlags Flags for the left button down message
+ * @param inPoint Point where the mouse was left clicked (client coordinates)
+ */
+//==============================================================================
+void CWebLink::OnLButtonDown(UINT inFlags, CPoint inPoint)
+{
+ UNREFERENCED_PARAMETER(inFlags);
+ UNREFERENCED_PARAMETER(inPoint);
+
+ if (IsWindowEnabled()) {
+ m_bCapture = FALSE;
+ ReleaseCapture();
+
+ m_bVisited = TRUE;
+ this->ShowLink();
+
+ this->JumpLink();
+ }
+}
+
+//==============================================================================
+/**
+ * OnContextMenu: Handle for the WM_CONTEXTMENU message.
+ *
+ * @param inWnd Window for the context menu.
+ * @param inPoint Mouse position when the right button was clicked.
+ */
+//==============================================================================
+void CWebLink::OnContextMenu(CWnd *inWnd, CPoint inPoint)
+{
+ UNREFERENCED_PARAMETER(inWnd);
+
+ BCMenu theContextMenu;
+ BCMenu *thePopupMenu = nullptr;
+ long theMenuCmd;
+
+ ReleaseCapture();
+
+ // Load the context menu
+ theContextMenu.LoadMenu(IDR_WEBLINK_CONTEXT_MENU);
+#ifdef _USECONTENTMENUIMAGES_
+ theContextMenu.SetBitmapBackground(MENU_IMAGELIST_BACKCOLOR);
+ theContextMenu.LoadToolbar(IDR_WEBLINKCONTEXTTOOLBAR);
+#endif
+
+ thePopupMenu = (BCMenu *)theContextMenu.GetSubMenu(0);
+
+ // Set the default menu item to "Open"
+ SetMenuDefaultItem(thePopupMenu->m_hMenu, IDM_OPENLINK, FALSE);
+
+ m_bPopup = TRUE;
+
+ // Show the context menu
+ theMenuCmd = (long)thePopupMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
+ inPoint.x, inPoint.y, this);
+
+ m_bPopup = FALSE;
+
+ m_bCapture = FALSE;
+
+ theContextMenu.DestroyMenu();
+
+ this->ShowLink();
+
+ // Handle the popup menu command
+
+ switch (theMenuCmd) {
+ case IDM_OPENLINK:
+ this->JumpLink();
+ break;
+
+ case IDM_COPYSHORTCUT2:
+ this->CopyShortcut();
+ break;
+
+ default:
+ break;
+ }
+
+ theContextMenu.DestroyMenu();
+}
+
+//==============================================================================
+/**
+ * CopyShortcut: Copy the link URL text to the clipboard.
+ *
+ * @param None
+ */
+//==============================================================================
+void CWebLink::CopyShortcut()
+{
+ // Open the clipboard so we can copy data to it.
+ if (OpenClipboard()) {
+ DWORD theBufferSize;
+ HGLOBAL theGlobalBuffer;
+ LPSTR theClipboardText;
+
+ // Determine the buffer size, based on the length of the URL
+ theBufferSize = m_URL.GetLength();
+
+ // Clear the contents of the clipboard
+ ::EmptyClipboard();
+
+ // Allocate a global buffer and copy the text to it
+ theGlobalBuffer = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, theBufferSize + 1);
+ theClipboardText = (LPSTR)GlobalLock(theGlobalBuffer);
+
+ CopyMemory(theClipboardText, m_URL, theBufferSize + 1);
+
+ // Unlock the buffer
+ GlobalUnlock(theGlobalBuffer);
+
+ // Pass the data to the clipboard
+ SetClipboardData(CF_TEXT, theGlobalBuffer);
+
+ // Close the clipboard, but do not GlobalFree() the global buffer
+ CloseClipboard();
+ }
+}
diff --git a/src/Authoring/Studio/_Win/Application/WebLink.h b/src/Authoring/Studio/_Win/Application/WebLink.h
new file mode 100644
index 00000000..4ca3dede
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Application/WebLink.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef _WEBLINK_H_
+#define _WEBLINK_H_
+
+#include "BaseLink.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CWebLink window
+
+class CWebLink : public CBaseLink
+{
+ // Construction
+public:
+ CWebLink();
+
+ // Attributes
+public:
+ // Operations
+public:
+ virtual void SetImage(UINT uiResBmp, bool bAutoSize = true);
+ virtual void SetImage(HBITMAP hBmp, bool bAutoSize = true);
+ virtual void SetText(CString inText);
+ virtual void SetURL(CString inURL);
+
+protected:
+ COLORREF m_ColorLink;
+ COLORREF m_ColorHighlight;
+ COLORREF m_ColorVisited;
+ COLORREF m_ColorBackground;
+
+ bool m_bVisited;
+ bool m_bPopup;
+
+ HBITMAP m_Bitmap;
+
+ CString m_URL;
+
+ virtual COLORREF GetColor();
+
+ virtual void CopyShortcut();
+
+ virtual void JumpLink();
+
+ virtual void OpenURL(CString inURL);
+
+ virtual void ShowLink();
+
+ virtual void ShowBitmapLink();
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CWebLink)
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ virtual ~CWebLink();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CWebLink)
+ virtual afx_msg BOOL OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message);
+ virtual afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+ virtual afx_msg void OnContextMenu(CWnd *pWnd, CPoint pos);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Controls/AppFonts.cpp b/src/Authoring/Studio/_Win/Controls/AppFonts.cpp
new file mode 100644
index 00000000..54039331
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/AppFonts.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "AppFonts.h"
+#include "StudioPreferences.h"
+#include "StringLoader.h"
+
+//=============================================================================
+/**
+ * Constructor for a CAppFonts object.
+ */
+//=============================================================================
+CAppFonts::CAppFonts()
+{
+ // Normal font
+ const QString theFontFace = CStudioPreferences::GetFontFaceName();
+ Q3DStudio::CString theFontSize = ::LoadResourceString(IDS_STUDIOFONT_SIZE);
+
+ m_NormalFont.setFamily(theFontFace);
+ m_NormalFont.setPointSize(13); // atoi( theFontSize.GetCharStar( ) );
+}
+
+//==============================================================================
+/**
+ * Releases the object.
+ */
+//==============================================================================
+CAppFonts::~CAppFonts()
+{
+}
+
+//==============================================================================
+/**
+ * Returns a pointer to the only instance of this class. Automatically cleaned
+ * up when the program exits.
+ */
+//==============================================================================
+CAppFonts *CAppFonts::GetInstance()
+{
+ static CAppFonts theAppFonts;
+ return &theAppFonts;
+}
+
+//==============================================================================
+/**
+ * Returns the normal font for use on GUI elements for the application.
+ */
+//==============================================================================
+QFont CAppFonts::GetNormalFont()
+{
+ return m_NormalFont;
+}
diff --git a/src/Authoring/Studio/_Win/Controls/AppFonts.h b/src/Authoring/Studio/_Win/Controls/AppFonts.h
new file mode 100644
index 00000000..e2036c0e
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/AppFonts.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#ifndef INCLUDED_APP_FONTS_H
+#define INCLUDED_APP_FONTS_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <QFont>
+//==============================================================================
+/**
+ * Dispatches commands
+ */
+//==============================================================================
+class CAppFonts
+{
+public:
+ CAppFonts();
+ virtual ~CAppFonts();
+ static CAppFonts *GetInstance();
+ QFont GetNormalFont();
+
+private:
+ QFont m_NormalFont;
+};
+
+#endif // INCLUDED_APP_FONTS_H
diff --git a/src/Authoring/Studio/_Win/Controls/BufferedRenderer.cpp b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.cpp
new file mode 100644
index 00000000..34076704
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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 "stdafx.h"
+
+#include "BufferedRenderer.h"
+#include "AppFonts.h"
+
+
+//=============================================================================
+/**
+ * Create a buffered renderer.
+ * @param inSize the size of this renderer.
+ */
+CBufferedRenderer::CBufferedRenderer(const QSize &inSize)
+ : CWinRenderer()
+{
+ m_CurrentBitmap = QPixmap(inSize);
+
+ // KDAB_TODO: I don't see why m_OldBitmap is needed, nor what is the difference between CBufferedRenderer and COffscreenRenderer
+ m_OldBitmap = m_CurrentBitmap;
+
+ m_painter = new QPainter(&m_CurrentBitmap);
+ QFont font = CAppFonts::GetInstance()->GetNormalFont();
+ m_painter->setFont(font);
+
+ m_Size = inSize;
+
+ PushClippingRect(QRect(QPoint(0,0), inSize));
+}
+
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CBufferedRenderer::~CBufferedRenderer()
+{
+ delete m_painter;
+ m_painter = nullptr;
+}
+
+//=============================================================================
+/**
+ * Copy this BufferedRenderer to inRenderer using alpha blend.
+ * This will semi-transparently copy the contents of this buffer to inRenderer
+ * using the alpha.
+ * @param inRenderer the destination renderer.
+ * @param inAlpha the opacity, 255 = opaque 0 = transparent.
+ */
+/*void CBufferedRenderer::TransparentBltTo( CRenderer* inRenderer, short inAlpha )
+{
+
+ CPt theDestination;
+ theDestination.Offset( inRenderer->GetTranslation( ) );
+
+ AlphaBlendExt( inRenderer->GetGraphicsDevice( )->m_hDC, (short)theDestination.x,
+(short)theDestination.y, (short)m_Size.x, (short)m_Size.y, m_DC->m_hDC, 0, 0, (short)m_Size.x,
+(short)m_Size.y, inAlpha );
+// ::DrawAlphaBlendBitmap( inRenderer->GetDC( ), (short)theDestination.x,
+(short)theDestination.y, m_CurrentBitmap, (short)m_Size.x, (short)m_Size.y, 0, 0, inAlpha );
+
+}*/
+
+//==============================================================================
+/**
+ * Draws a bitmap using alpha blending. Works in NT/2000/9x
+ *
+ * @param inDCDest Destination device context
+ * @param inX X coordinate for drawing
+ * @param inY Y coordinate for drawing
+ * @param inWidth Drawing width
+ * @param inHeight Drawing height
+ * @param inDCSrc Source device context
+ * @param inSourceX X source coordinate
+ * @param inSourceY Y source coordinate
+ * @param inSourceWidth Source drawing width
+ * @param inSourceHeight Source drawing height
+ * @param inAlpha Alpha blend: 0-255, where 255 is opaque
+ */
+//==============================================================================
+/*bool CBufferedRenderer::AlphaBlendExt( HDC inDCDest, short inX, short inY, short inWidth, short
+inHeight, HDC inDCSrc, short inSourceX, short inSourceY, short inSourceWidth, short inSourceHeight,
+short inAlpha )
+{
+ BITMAPINFOHEADER theBMI;
+
+ theBMI.biSize = sizeof( BITMAPINFOHEADER );
+ theBMI.biWidth = inWidth;
+ theBMI.biHeight = inHeight;
+ theBMI.biPlanes = 1;
+ theBMI.biBitCount = 32; // 24 bits + alpha channel
+ theBMI.biCompression = BI_RGB; // no compression
+ theBMI.biSizeImage = 0;
+ theBMI.biXPelsPerMeter = 0;
+ theBMI.biYPelsPerMeter = 0;
+ theBMI.biClrUsed = 0; // use the whole palette
+ theBMI.biClrImportant = 0;
+
+ BYTE* theSrcBits;
+ HBITMAP theBmpSrc;
+
+ // Create DIB section in shared memory
+ theBmpSrc = CreateDIBSection( inDCSrc, ( BITMAPINFO* ) &theBMI, DIB_RGB_COLORS, ( void** )
+&theSrcBits, 0, 0L );
+
+ BYTE* theDestBits;
+ HBITMAP theBmpDest;
+
+ // Create DIB section in shared memory
+ theBmpDest = CreateDIBSection( inDCDest, ( BITMAPINFO* ) &theBMI, DIB_RGB_COLORS, ( void** )
+&theDestBits, 0, 0L );
+
+ // Copy our source and destination bitmaps onto our DIBSections.
+ // so we can get access to their bits using the BYTE*'s we used
+ // in the CreateDIBSection()s above.
+
+ HDC theDC = CreateCompatibleDC( nullptr );
+
+ HBITMAP theDCOld = ( HBITMAP ) SelectObject( theDC, theBmpSrc );
+
+ if ( !StretchBlt( theDC, 0, 0, inWidth, inHeight, inDCSrc, inSourceX, inSourceY,
+inSourceWidth, inSourceHeight, SRCCOPY ) )
+ {
+ SelectObject( theDC, theDCOld );
+ DeleteDC( theDC );
+ DeleteObject( theBmpSrc );
+ DeleteObject( theBmpDest );
+ return false;
+ }
+
+ SelectObject( theDC, theBmpDest );
+
+ if (! StretchBlt( theDC, 0, 0, inWidth, inHeight, inDCDest, inX, inY, inWidth, inHeight,
+SRCCOPY ) )
+ {
+ SelectObject( theDC, theDCOld );
+ DeleteDC( theDC );
+ DeleteObject( theBmpSrc );
+ DeleteObject( theBmpDest );
+ return true;
+ }
+
+ SelectObject( theDC, theDCOld );
+ DeleteDC( theDC );
+
+ short theXLoop, theYLoop;
+
+ for( theYLoop=0; theYLoop<inHeight; ++theYLoop )
+ {
+ LPBYTE theDestRGB = ( LPBYTE ) &( ( DWORD* ) theDestBits)[theYLoop * inWidth];
+ LPBYTE theSrcRGB = ( LPBYTE ) &( ( DWORD* ) theSrcBits)[theYLoop * inWidth];
+
+ for( theXLoop=0; theXLoop<inWidth; theXLoop++ )
+ {
+ theSrcRGB[0] = ( BYTE ) ( ( theDestRGB[0] * ( 255 - inAlpha ) + theSrcRGB[0]
+* inAlpha ) >> 8 );
+ theSrcRGB[1] = ( BYTE ) ( ( theDestRGB[1] * ( 255 - inAlpha ) + theSrcRGB[1]
+* inAlpha ) >> 8 );
+ theSrcRGB[2] = ( BYTE ) ( ( theDestRGB[2] * ( 255 - inAlpha ) + theSrcRGB[2]
+* inAlpha ) >> 8 );
+
+ theSrcRGB += 4;
+ theDestRGB += 4;
+ }
+ }
+
+ theDC = CreateCompatibleDC( nullptr );
+
+ theDCOld = ( HBITMAP ) SelectObject( theDC, theBmpSrc );
+
+ if ( !BitBlt( inDCDest, inX, inY, inWidth, inHeight, theDC, 0, 0, SRCCOPY ) )
+ {
+ SelectObject( theDC, theDCOld );
+ DeleteDC( theDC );
+ DeleteObject( theBmpSrc );
+ DeleteObject( theBmpDest );
+ return false;
+ }
+
+ SelectObject( theDC, theDCOld );
+ DeleteDC( theDC );
+
+ DeleteObject( theBmpSrc );
+ DeleteObject( theBmpDest );
+
+ return true;
+}*/
diff --git a/src/Authoring/Studio/_Win/Controls/BufferedRenderer.h b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.h
new file mode 100644
index 00000000..19cc8f78
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_BUFFERED_RENDERER_H
+#define INCLUDED_BUFFERED_RENDERER_H 1
+
+#pragma once
+
+#include "WinRenderer.h"
+
+#include <QPainter>
+#include <QPixmap>
+#include <QFont>
+
+class CBufferedRenderer : public CWinRenderer
+{
+public:
+ CBufferedRenderer(const QSize &inSize);
+
+ virtual ~CBufferedRenderer();
+ QPixmap pixmap() const override { return m_CurrentBitmap;}
+
+ // void TransparentBltTo( CRenderer* inRenderer, short inAlpha );
+
+protected:
+ QPixmap m_OldBitmap;
+ QPixmap m_CurrentBitmap;
+ QSize m_Size;
+
+ // bool AlphaBlendExt( HDC inDCDest, short inX, short inY, short inWidth, short inHeight, HDC
+ //inDCSrc, short inSourceX, short inSourceY, short inSourceWidth, short inSourceHeight, short
+ //inAlpha );
+};
+#endif // INCLUDED_BUFFERED_RENDERER_H
diff --git a/src/Authoring/Studio/_Win/Controls/MFCEditControl.cpp b/src/Authoring/Studio/_Win/Controls/MFCEditControl.cpp
new file mode 100644
index 00000000..19b263d9
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/MFCEditControl.cpp
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "MFCEditControl.h"
+
+//==============================================================================
+// Implementation
+//==============================================================================
+
+#ifdef USE_RICHEDIT
+IMPLEMENT_DYNAMIC(CMFCEditControl, CRichEditCtrl)
+#else
+IMPLEMENT_DYNAMIC(CMFCEditControl, CEdit)
+#endif
+
+CMFCEditControl::CMFCEditControl()
+ : m_Changed(false)
+ , m_HotKeys(nullptr)
+{
+}
+
+CMFCEditControl::~CMFCEditControl()
+{
+ // This control's window has been destroyed by PlatformEditControl,
+ // so a SigTextCommit is potentially dangerous as it will lead to GetText (below)
+ // which will try to get text from a destroyed window.
+ // However, if this is needed, note that CEdit works, but CRichEditCtrl don't.
+ // Can revert to using CEdit by commenting out the line in MFCEditControl.h
+
+ // if ( m_Changed )
+ //{
+ // m_Changed = false;
+ // SigTextCommit( );
+ //}
+}
+
+Q3DStudio::CString CMFCEditControl::GetText()
+{
+ Q3DStudio::CString theResult;
+
+#ifdef USE_RICHEDIT
+ GETTEXTLENGTHEX getTextLengthEx;
+ getTextLengthEx.flags = GTL_DEFAULT | GTL_USECRLF;
+ getTextLengthEx.codepage = 1200;
+ LRESULT lResult = SendMessage(EM_GETTEXTLENGTHEX, (WPARAM)&getTextLengthEx, 0);
+ if (lResult > 0) {
+ GETTEXTEX getTextEx;
+ getTextEx.cb = (DWORD)(lResult + 2);
+ getTextEx.codepage = 1200;
+ getTextEx.flags = GT_DEFAULT | GT_USECRLF;
+ getTextEx.lpDefaultChar = nullptr;
+ getTextEx.lpUsedDefChar = nullptr;
+ wchar_t *ws = new wchar_t[lResult / 2 + 1];
+ SendMessage(EM_GETTEXTEX, (WPARAM)&getTextEx, (LPARAM)ws);
+ theResult = ws;
+ delete[] ws;
+ }
+#else
+ ::CString theWindowText;
+ GetWindowText(theWindowText);
+ // normal gettext, which depends on machine's locale
+ theResult = theWindowText;
+#endif
+
+ return theResult;
+}
+
+void CMFCEditControl::SetText(const Q3DStudio::CString &inText)
+{
+ // The text manipulation is actually already being handled by the CEdit/CWnd
+ // This SetText is called by our custom CPropertyMultilineEdit and screws with the MFC's
+ // own text handling functions.
+ // Essentially, we still need this to set up the initial use of the MFC Edit.
+ if (GetText() == "") {
+#ifdef USE_RICHEDIT
+ SETTEXTEX setTextEx;
+ setTextEx.codepage = 1200;
+ setTextEx.flags = ST_DEFAULT;
+ SendMessage(EM_SETTEXTEX, (WPARAM)&setTextEx,
+ (LPARAM)(static_cast<const wchar_t *>(inText)));
+#else
+ // normal settext, which depends on machine's locale
+ SetWindowText(inText.GetMulti());
+#endif
+ }
+}
+
+#ifdef USE_RICHEDIT
+BEGIN_MESSAGE_MAP(CMFCEditControl, CRichEditCtrl)
+#else
+BEGIN_MESSAGE_MAP(CMFCEditControl, CEdit)
+#endif
+ON_CONTROL_REFLECT(EN_CHANGE, OnEnChange)
+ON_WM_LBUTTONDBLCLK()
+ON_WM_SETFOCUS()
+ON_WM_KILLFOCUS()
+END_MESSAGE_MAP()
+
+// CMFCEditControl message handlers
+
+void CMFCEditControl::OnEnChange()
+{
+ m_Changed = true;
+ SigTextChanged();
+}
+
+void CMFCEditControl::OnLButtonDblClk(UINT inSomething, CPoint inPoint)
+{
+#ifdef USE_RICHEDIT
+ CRichEditCtrl::OnLButtonDblClk(inSomething, inPoint);
+#else
+ CEdit::OnLButtonDblClk(inSomething, inPoint);
+#endif
+
+ // select all text in this CEdit/CRichEditCtrl
+ SetSel(0, -1);
+}
+
+void CMFCEditControl::OnSetFocus(CWnd *inWnd)
+{
+#ifdef USE_RICHEDIT
+ CRichEditCtrl::OnSetFocus(inWnd);
+#else
+ CEdit::OnSetFocus(inWnd);
+#endif
+
+ m_Changed = false;
+}
+
+void CMFCEditControl::OnKillFocus(CWnd *inWnd)
+{
+#ifdef USE_RICHEDIT
+ CRichEditCtrl::OnKillFocus(inWnd);
+#else
+ CEdit::OnKillFocus(inWnd);
+#endif
+
+ if (m_Changed) {
+ m_Changed = false;
+ SigTextCommit();
+ }
+}
+
+BOOL CMFCEditControl::PreTranslateMessage(MSG *pMsg)
+{
+ if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) {
+ // Reserve some keys for Studio's hotkeys
+ // This is only a subset of Studio's hotkeys as listed in
+ // CWorkspace::RegisterGlobalKeyboardShortcuts( CHotKeys* inShortcutHandler )
+ // We need to make sure that EditControl's hotkeys won't collide with Studio's hotkeys
+ bool theReservedHotKeys = false;
+ if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN
+ || pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP) {
+ if (pMsg->wParam >= CHotKeys::KEY_F1
+ && pMsg->wParam
+ <= CHotKeys::KEY_F12) // F1 to F12 keys, this may fail if not in windows
+ {
+ theReservedHotKeys = true;
+ } else if (CHotKeys::IsKeyDown(VK_CONTROL)) {
+ unsigned int theCharacterCode = ::MapVirtualKey(static_cast<UINT>(pMsg->wParam), 2);
+
+ switch (theCharacterCode) {
+ case 's':
+ case 'S': // save file / save file as
+ case 'o':
+ case 'O': // open file
+ case 'n':
+ case 'N': // new file
+ theReservedHotKeys = true;
+ }
+ }
+ }
+
+ if (theReservedHotKeys) {
+ if (m_HotKeys != nullptr)
+ m_HotKeys->PreTranslateMessage(pMsg);
+ } else {
+ // no idea what all that filtering does, since Bug 1695 appears to be working
+ // and it is causing problem with Japanese text input (2639)
+ ::TranslateMessage(pMsg);
+ ::DispatchMessage(pMsg);
+ }
+ return TRUE;
+
+ //// This is REALLY bad, but it's basically filtering all the messages that it thinks it
+ ///might want and handles those.
+ // if ((::GetAsyncKeyState(VK_LBUTTON) & 0x8000) == 0 && (::GetAsyncKeyState(VK_RBUTTON) &
+ // 0x8000) == 0)
+ //{
+ // unsigned int theChar = pMsg->wParam;
+
+ // /*
+ // * VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)
+ // * 0x40 : unassigned
+ // * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)
+ // */
+
+ // /*
+ // #define VK_OEM_1 0xBA // ';:' for US
+ // #define VK_OEM_PLUS 0xBB // '+' any country
+ // #define VK_OEM_COMMA 0xBC // ',' any country
+ // #define VK_OEM_MINUS 0xBD // '-' any country
+ // #define VK_OEM_PERIOD 0xBE // '.' any country
+ // #define VK_OEM_2 0xBF // '/?' for US
+ // #define VK_OEM_3 0xC0 // '`~' for US
+ // #define VK_OEM_4 0xDB // '[{' for US
+ // #define VK_OEM_5 0xDC // '\|' for US
+ // #define VK_OEM_6 0xDD // ']}' for US
+ // #define VK_OEM_7 0xDE // ''"' for US
+ // #define VK_OEM_8 0xDF
+ // */
+
+ // if ( theChar == VK_RETURN || theChar == VK_BACK || theChar == VK_MENU ||
+ // ( theChar >= VK_SPACE && theChar < VK_LWIN ) ||
+ // ( theChar >= VK_OEM_1 && theChar <= VK_OEM_8 )
+ // )
+ // {
+ // ::TranslateMessage( pMsg );
+ // ::DispatchMessage( pMsg );
+ // return TRUE;
+ // }
+ //}
+ }
+
+#ifdef USE_RICHEDIT
+ return CRichEditCtrl::PreTranslateMessage(pMsg);
+#else
+ return CEdit::PreTranslateMessage(pMsg);
+#endif
+}
+
+BOOL CMFCEditControl::Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID)
+{
+// TODO: Add your specialized code here and/or call the base class
+
+#ifdef USE_RICHEDIT
+ BOOL theResult = CRichEditCtrl::Create(dwStyle, rect, pParentWnd, nID);
+ SetEventMask(GetEventMask() | ENM_CHANGE);
+#else
+ BOOL theResult = CEdit::Create(dwStyle, rect, pParentWnd, nID);
+#endif
+
+ return theResult;
+}
diff --git a/src/Authoring/Studio/_Win/Controls/MFCEditControl.h b/src/Authoring/Studio/_Win/Controls/MFCEditControl.h
new file mode 100644
index 00000000..9d688fdc
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/MFCEditControl.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "HotKeys.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+
+// RichEditCtrl, though super useful, has some stability issue to be ironed out.
+// Use CEdit by commenting out the line below if it is causing crashes.
+#define USE_RICHEDIT
+
+#ifdef USE_RICHEDIT
+class CMFCEditControl : public CRichEditCtrl
+#else
+class CMFCEditControl : public CEdit
+#endif
+{
+protected:
+ DECLARE_DYNAMIC(CMFCEditControl)
+
+public:
+ boost::signal<void()> SigTextChanged;
+ boost::signal<void()> SigTextCommit;
+
+protected:
+ bool m_Changed;
+ CHotKeys *m_HotKeys; // global keyboard shortcut (Studio's hotkeys)
+
+public:
+ CMFCEditControl();
+ virtual ~CMFCEditControl();
+
+ Q3DStudio::CString GetText();
+ void SetText(const Q3DStudio::CString &inText);
+
+ void SetGlobalKeyboardShortcuts(CHotKeys *inHotKeys) { m_HotKeys = inHotKeys; }
+
+protected:
+ DECLARE_MESSAGE_MAP()
+public:
+ afx_msg void OnEnChange();
+ afx_msg void OnLButtonDblClk(UINT, CPoint);
+ afx_msg void OnSetFocus(CWnd *);
+ afx_msg void OnKillFocus(CWnd *);
+
+ virtual BOOL PreTranslateMessage(MSG *inMessage);
+ virtual BOOL Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID);
+};
diff --git a/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.cpp b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.cpp
new file mode 100644
index 00000000..72a5f17b
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "OffscreenRenderer.h"
+#include "AppFonts.h"
+
+//=============================================================================
+/**
+ * Constructor: Overrides a protected constructor on the base class. Sets up
+ * all the requirements so that this renderer is valid.
+ */
+COffscreenRenderer::COffscreenRenderer(const QRect &inClippingRect)
+ : CWinRenderer()
+{
+ m_pixmap = QPixmap(inClippingRect.size());
+ m_painter = new QPainter(&m_pixmap);
+ QFont font = CAppFonts::GetInstance()->GetNormalFont();
+ m_painter->setFont(font);
+
+ // Set up the specified clipping region. Renderer is now valid for use.
+ PushClippingRect(inClippingRect);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+COffscreenRenderer::~COffscreenRenderer()
+{
+ delete m_painter;
+ m_painter = nullptr;
+}
diff --git a/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.h b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.h
new file mode 100644
index 00000000..dccd259f
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_OFFSCREEN_RENDERER_H
+#define INCLUDED_OFFSCREEN_RENDERER_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "WinRenderer.h"
+
+//=============================================================================
+/**
+ * Class for creating a renderer compatible with the current display, but that
+ * does not actually draw to the display. Provided so that you controls can
+ * query text size outside of their draw functions. This class could be
+ * further extended to provide offscreen drawing and blitting, though it's
+ * not currently set up to do so.
+ */
+class COffscreenRenderer : public CWinRenderer
+{
+public:
+ COffscreenRenderer(const QRect &inClippingRect);
+ virtual ~COffscreenRenderer();
+
+ QPixmap pixmap() const override { return m_pixmap;}
+
+protected:
+ QPixmap m_pixmap;
+};
+
+#endif // INCLUDED_OFFSCREEN_RENDERER_H
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformEditControl.cpp b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.cpp
new file mode 100644
index 00000000..4c581806
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PlatformEditControl.h"
+#include "Renderer.h"
+#include "StudioPreferences.h"
+
+#ifdef WIN32
+
+CPlatformEditControl::CPlatformEditControl(UICRenderDevice inParent)
+ : CPlatformWindowControl(inParent)
+{
+#ifdef USE_RICHEDIT
+ BOOL theReturn = m_EditWindow.Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE
+ | ES_WANTRETURN | ES_AUTOVSCROLL,
+ CRect(0, 0, 0, 0), CWnd::FromHandle(inParent), 1);
+#else
+ BOOL theReturn = m_EditWindow.CreateEx(0, _T("EDIT"), "", WS_CHILD | WS_VSCROLL | ES_MULTILINE
+ | ES_WANTRETURN | ES_AUTOVSCROLL,
+ 0, 0, 0, 0, inParent, nullptr);
+#endif
+ ASSERT(theReturn);
+
+ Q_UNUSED(theReturn); // for release builds
+
+ m_EditWindow.SigTextChanged.connect(std::bind(&CPlatformEditControl::OnTextChanged, this));
+ m_EditWindow.SigTextCommit.connect(std::bind(&CPlatformEditControl::OnTextCommit, this));
+
+ m_Font.CreatePointFont(
+ 80, CString(CStudioPreferences::GetFontFaceName())); // size specified in 1/10ths of a point
+ m_EditWindow.SetFont(&m_Font);
+ m_EditWindow.SetTextMode(TM_PLAINTEXT | TM_MULTILEVELUNDO);
+ m_EditWindow.SetBackgroundColor(FALSE, CStudioPreferences::GetLightBaseColor());
+
+ m_Window = m_EditWindow.GetSafeHwnd();
+}
+
+CPlatformEditControl::~CPlatformEditControl()
+{
+ m_EditWindow.DestroyWindow();
+}
+
+//=============================================================================
+/**
+ * Essentially, this just turns the window off. Do not use the CControl::SetVisible
+ * because that would screw with the control's size and you will notice the inspector
+ * palette having cut off rows.
+ *
+ * @param inIsVisible If the window should be visible
+ */
+void CPlatformEditControl::SetWindowVisible(bool inIsVisible)
+{
+ if (inIsVisible)
+ m_EditWindow.ShowWindow(SW_SHOWNORMAL);
+ else
+ m_EditWindow.ShowWindow(SW_HIDE);
+}
+
+void CPlatformEditControl::OnTextChanged()
+{
+ SigTextChanged();
+}
+
+void CPlatformEditControl::OnTextCommit()
+{
+ SigTextCommit();
+}
+
+void CPlatformEditControl::SetText(const Q3DStudio::CString &inText)
+{
+ m_EditWindow.SetText(inText);
+}
+
+Q3DStudio::CString CPlatformEditControl::GetText()
+{
+ return m_EditWindow.GetText();
+}
+
+void CPlatformEditControl::EnableWindow(bool inEnable)
+{
+ m_EditWindow.EnableWindow(inEnable);
+}
+
+//==============================================================================
+// CControl
+//==============================================================================
+
+void CPlatformEditControl::Draw(CRenderer *inRenderer)
+{
+ // Create a clipping region for the MFC Edit
+ CRct theUICClipRect = inRenderer->GetClippingRect();
+ RECT theRect(theUICClipRect);
+ CRgn theClipRgn;
+ theClipRgn.CreateRectRgnIndirect(&theRect);
+ HRGN theClipHandle = (HRGN)theClipRgn;
+ m_EditWindow.SetWindowRgn(theClipHandle, TRUE);
+
+ if (m_EditWindow.IsWindowVisible() == FALSE)
+ m_EditWindow.ShowWindow(SW_SHOWNORMAL);
+
+ // Draw a bounding box around the entire control
+ CColor theTopColor = CStudioPreferences::GetControlRectTopLineColor();
+ CColor theSideColor = CStudioPreferences::GetControlRectSideLineColor();
+ CColor theBottomColor = CStudioPreferences::GetControlRectBottomLineColor();
+
+ inRenderer->DrawRectOutline(GetSize(), theTopColor, theSideColor, theBottomColor, theSideColor);
+}
+
+#endif // WIN32
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformEditControl.h b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.h
new file mode 100644
index 00000000..1347b217
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PLATFORM_EDIT_CONTROL_H
+#define INCLUDED_PLATFORM_EDIT_CONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "PlatformWindowControl.h"
+#include "MFCEditControl.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+
+#ifdef WIN32
+
+class CPlatformEditControl : public CPlatformWindowControl
+{
+protected:
+ CFont m_Font; ///< MFC font for the edit text
+ CMFCEditControl m_EditWindow; ///< MFC Edit Window
+
+public:
+ std::signal0<void> SigTextChanged;
+ std::signal0<void> SigTextCommit;
+
+public:
+ CPlatformEditControl(UICRenderDevice inParent);
+ virtual ~CPlatformEditControl();
+
+ void SetWindowVisible(bool inIsVisible);
+
+ void SetText(const Q3DStudio::CString &inText);
+ Q3DStudio::CString GetText();
+ void EnableWindow(bool inEnable);
+
+ void SetGlobalKeyboardShortcuts(CHotKeys *inHotKeys)
+ {
+ m_EditWindow.SetGlobalKeyboardShortcuts(inHotKeys);
+ }
+
+ // CControl
+ virtual void Draw(CRenderer *inRenderer);
+
+protected:
+ void OnTextChanged();
+ void OnTextCommit();
+};
+
+#endif // WIN32
+
+#endif // INCLUDED_PLATFORM_EDIT_CONTROL_H
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.cpp b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.cpp
new file mode 100644
index 00000000..fc2c2509
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PlatformStaticControl.h"
+
+#ifdef WIN32
+
+CPlatformStaticControl::CPlatformStaticControl(UICRenderDevice inParent)
+ : CPlatformWindowControl(inParent)
+{
+ BOOL theReturn = m_EditWindow.CreateEx(0, _T("STATIC"), _T(""), WS_VISIBLE | WS_CHILD, 0, 0, 0,
+ 0, inParent, nullptr);
+ ASSERT(theReturn);
+ theReturn;
+
+ m_Font.CreatePointFont(
+ 80, CString(CStudioPreferences::GetFontFaceName())); // size specified in 1/10ths of a point
+ m_EditWindow.SetFont(&m_Font);
+
+ m_Window = m_EditWindow.GetSafeHwnd();
+}
+
+CPlatformStaticControl::~CPlatformStaticControl()
+{
+ m_EditWindow.DestroyWindow();
+}
+
+void CPlatformStaticControl::SetText(const Q3DStudio::CString &inText)
+{
+ m_EditWindow.SetWindowText(inText);
+}
+
+#endif // WIN32 \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.h b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.h
new file mode 100644
index 00000000..e8b68fa6
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_PLATFORM_STATIC_CONTROL_H
+#define INCLUDED_PLATFORM_STATIC_CONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+
+#include "PlatformWindowControl.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+class CPlatformStaticControl : public CPlatformWindowControl
+{
+protected:
+ CFont m_Font; ///< MFC font for the static text
+ CStatic m_EditWindow; ///< MFC Edit Window
+
+public:
+ CPlatformStaticControl(UICRenderDevice inParent);
+ virtual ~CPlatformStaticControl();
+
+ void SetText(const Q3DStudio::CString &inText);
+};
+
+#endif // WIN32
+
+#endif // INCLUDED_PLATFORM_STATIC_CONTROL_H
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.cpp b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.cpp
new file mode 100644
index 00000000..89279702
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Include
+//==============================================================================
+#include "PlatformWindowControl.h"
+
+CPlatformWindowControl::CPlatformWindowControl(UICRenderDevice inParent)
+ : m_Window(nullptr)
+{
+ inParent;
+}
+
+CPlatformWindowControl::~CPlatformWindowControl()
+{
+}
+
+//==============================================================================
+// CControl
+//==============================================================================
+
+void CPlatformWindowControl::SetPosition(CPt inPosition)
+{
+ CControl::SetPosition(inPosition);
+
+ CPt theGlobalPosition = CControl::GetGlobalPosition(CPt(0, 0));
+
+ ::SetWindowPos(m_Window, nullptr, theGlobalPosition.x + 1, theGlobalPosition.y + 1, 0, 0,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
+}
+
+void CPlatformWindowControl::SetSize(CPt inSize)
+{
+ CControl::SetSize(inSize);
+
+ ::SetWindowPos(m_Window, nullptr, 0, 0, inSize.x - 2, inSize.y - 2,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
+}
+
+void CPlatformWindowControl::Invalidate(bool inInvalidate)
+{
+ CControl::Invalidate(inInvalidate);
+
+ // This is neccesary to handle the scroll behavior when
+ // this item is embedded in a scroll window.
+ CPt theGlobalPosition = CControl::GetGlobalPosition(CPt(0, 0));
+ ::SetWindowPos(m_Window, nullptr, theGlobalPosition.x + 1, theGlobalPosition.y + 1, 0, 0,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
+}
+
+void CPlatformWindowControl::OnVisibleStateChange(bool inIsVisible)
+{
+ ::ShowWindow(m_Window, ((inIsVisible) ? (SW_SHOWNORMAL) : (SW_HIDE)));
+}
+
+void CPlatformWindowControl::OnParentVisibleStateChanged(bool inIsVisible)
+{
+ ::ShowWindow(m_Window, ((inIsVisible) ? (SW_SHOWNORMAL) : (SW_HIDE)));
+}
+
+UICRenderDevice CPlatformWindowControl::GetPlatformDevice()
+{
+ return m_Window;
+}
diff --git a/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.h b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.h
new file mode 100644
index 00000000..f76697f6
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_PLATFORM_WINDOW_CONTROL_H
+#define INCLUDED_PLATFORM_WINDOW_CONTROL_H 1
+
+#pragma once
+
+//==============================================================================
+// Include
+//==============================================================================
+
+#include "Control.h"
+
+//==============================================================================
+// Class
+//==============================================================================
+
+class CPlatformWindowControl : public CControl
+{
+protected:
+ UICRenderDevice m_Window; ///<
+
+public:
+ CPlatformWindowControl(UICRenderDevice inParent);
+ virtual ~CPlatformWindowControl();
+
+ // CControl
+ void SetPosition(CPt inPosition) override;
+ void SetSize(CPt inSize) override;
+ void Invalidate(bool inInvalidate = true) override;
+
+ void OnVisibleStateChange(bool inIsVisible) override;
+ void OnParentVisibleStateChanged(bool inIsVisible) override;
+
+ UICRenderDevice GetPlatformDevice() override;
+};
+
+#endif // INCLUDED_PLATFORM_WINDOW_CONTROL_H
diff --git a/src/Authoring/Studio/_Win/Controls/WinRenderer.cpp b/src/Authoring/Studio/_Win/Controls/WinRenderer.cpp
new file mode 100644
index 00000000..3b9cddf1
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/WinRenderer.cpp
@@ -0,0 +1,525 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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 "stdafx.h"
+
+#include "WinRenderer.h"
+#include "MasterP.h"
+#include <math.h>
+#include "CoreUtils.h"
+
+//=============================================================================
+/**
+ * Leaves the Renderer in an invalid state, only for subclasses.
+ * In order for this renderer to be valid, you must do two things: (1) you must
+ * create a CDC and set m_DC equal to it, and (2) you must call PushClippingRect.
+ */
+CWinRenderer::CWinRenderer()
+ : m_painter(nullptr)
+{
+}
+
+//=============================================================================
+/**
+ * Leaves the Renderer in an invalid state, only for subclasses.
+ * PushClippingRect must be called in order for this to become valid.
+ */
+CWinRenderer::CWinRenderer(QPainter *inDC)
+{
+ m_painter = inDC;
+}
+
+CWinRenderer::CWinRenderer(QPainter *inDC, const QRect &inClippingRect)
+{
+ m_painter = inDC;
+
+ PushClippingRect(inClippingRect);
+}
+
+CWinRenderer::~CWinRenderer()
+{
+ m_Pens.clear();
+}
+
+//=============================================================================
+/**
+ * Draws a rectangle and fills it with inColor.
+ * The rectangle has no border and is solid.
+ * The coordinates are converted to global space using the current translation.
+ * @param inCoordinates the coordinates of the rectangle.
+ * @param inColor the color of the rectangle to draw.
+ */
+void CWinRenderer::FillSolidRect(const QRect &inCoordinates, const QColor &inColor)
+{
+ QRect theRect(inCoordinates.topLeft() + m_Translation,
+ inCoordinates.size());
+
+ m_painter->fillRect(theRect, inColor);
+}
+
+//=============================================================================
+/**
+ * Move the pen to the position.
+ * This will put the pen at inPoint but will not draw a line there from the
+ * current location.
+ * @param inPoint the location to move to, in local coordinates.
+ */
+void CWinRenderer::MoveTo(const QPoint &inPoint)
+{
+ m_currentPos = inPoint + m_Translation;
+}
+
+//=============================================================================
+/**
+ * Move the pen to the position.
+ * This will put the pen to the point but will not draw a line there from the
+ * current location.
+ * @param inX the X location to move to, in local coordinates.
+ * @param inY the Y location to move to, in local coordinates.
+ */
+void CWinRenderer::MoveTo(long inX, long inY)
+{
+ MoveTo(QPoint(inX, inY));
+}
+
+//=============================================================================
+/**
+ * Draw a line from the current pen location to inPoint.
+ * This will draw a line to inPoint and move the current location of the pen
+ * to inPoint.
+ * @param inPoint the location to draw to, in local coordinates.
+ */
+void CWinRenderer::LineTo(const QPoint &inPoint)
+{
+ const QPoint point = inPoint + m_Translation;
+ m_painter->drawLine(m_currentPos, point);
+ m_painter->drawLine(point, QPoint(point.x(), point.y() + 1));
+ m_currentPos = point;
+}
+
+//=============================================================================
+/**
+ * Draw a line from the current pen location to the point.
+ * This will draw a line to the point and move the current location of the pen
+ * to inPoint.
+ * @param inX the X coordinate of the point to draw to, in local coordinates.
+ * @param inY the Y coordinate of the point to draw to, in local coordinates.
+ */
+void CWinRenderer::LineTo(long inX, long inY)
+{
+ LineTo(QPoint(inX, inY));
+}
+
+//=============================================================================
+/**
+ * Change the active pen color.
+ * This acts as a stack so that it does not interfere with previous components.
+ * Once the color is done being used PopPen should be called.
+ * @param inColor the color to make the current pen.
+ * @param inWidth the pen width, in pixels.
+ */
+void CWinRenderer::PushPen(const QColor &inColor, int inWidth)
+{
+ QPen thePen = GetPen(inColor, inWidth, Qt::SolidLine);
+
+ QPen theCurrentPen = m_painter->pen();
+ m_painter->setPen(thePen);
+ m_PenList.push_back(theCurrentPen);
+}
+
+void CWinRenderer::PopPen()
+{
+ QPen thePen = m_PenList.back();
+ m_PenList.pop_back();
+ m_painter->setPen(thePen);
+}
+
+//=============================================================================
+/**
+ * Copy the bits from another renderer into this one.
+ * This will copy the rect from inRenderer into this renderer.
+ * inRect will be offset by this renderer's current translation. inXSrc and inYSrc
+ * will be offset by inRenderer's current translation.
+ * @param inRect the position and size of the area to be copied into this renderer.
+ * @param inPixmap the renderer to copy from.
+ * @param xSrc the x location of the location to copy from in inRenderer.
+ * @param ySrc the y location of the location to copy from in inRenderer.
+ */
+void CWinRenderer::BitBltFrom(const QRect &inRect, CRenderer *inRenderer, long inXSrc, long inYSrc)
+{
+ const auto inTranslation = inRenderer->GetTranslation();
+ inXSrc += inTranslation.x();
+ inYSrc += inTranslation.y();
+
+ auto srcRect = inRect;
+ auto destRect = inRect;
+ destRect.translate(m_Translation);
+ srcRect.moveTo(inXSrc, inYSrc);
+ m_painter->save();
+ m_painter->setCompositionMode(QPainter::CompositionMode_DestinationOver);
+ m_painter->drawPixmap(destRect, inRenderer->pixmap(), srcRect);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Draws text out without clipping it.
+ * @param inPoint the point at which to draw the text. (upper left corner)
+ * @param inText the text to draw.
+ */
+void CWinRenderer::DrawText(float inX, float inY, const QString &inText)
+{
+ inX += m_Translation.x();
+ inY += m_Translation.y();
+ m_painter->drawText(QPointF(inX, inY), inText);
+}
+
+//=============================================================================
+/**
+ * Draws text out to a clipped rectangle.
+ * If any text occurs outside the bounding box then it will be clipped.
+ * @param inPoint the point at which to draw the text. (upper left corner)
+ * @param inText the text to draw.
+ * @param inBoundingBox the bounding box used to clip the text.
+ * @param inColor color to draw the text in
+ */
+void CWinRenderer::DrawText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingBox, const QColor &inColor)
+{
+ inX += m_Translation.x();
+ inY += m_Translation.y();
+
+ QRectF rect(inBoundingBox);
+ rect.translate(inX, inY);
+ m_painter->save();
+ QPen pen(inColor);
+ m_painter->setPen(pen);
+ m_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, inText);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Draws BOLD text out to a clipped rectangle.
+ * If any text occurs outside the bounding box then it will be clipped.
+ * @param inPoint the point at which to draw the text. (upper left corner)
+ * @param inText the text to draw.
+ * @param inBoundingBox the bounding box used to clip the text.
+ * @param inColor color to draw the text in
+ */
+void CWinRenderer::DrawBoldText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingBox, const QColor &inColor)
+{
+ inX += m_Translation.x();
+ inY += m_Translation.y();
+
+ QRectF rect(inBoundingBox);
+ rect.translate(inX, inY);
+ m_painter->save();
+ QPen pen(inColor);
+ m_painter->setPen(pen);
+ QFont font = m_painter->font();
+ font.setBold(true);
+ m_painter->setFont(font);
+ m_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, inText);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Gets the dimensions of the text string as it would be written out to the
+ * screen.
+ * @param inText the text to check the length on.
+ * @return the length of the text in pixels.
+ */
+QSize CWinRenderer::GetTextSize(const QString &inText)
+{
+ QFontMetrics fm = m_painter->fontMetrics();
+ return fm.size(Qt::TextSingleLine, inText);
+}
+
+//=============================================================================
+/**
+ * Draws a a three-dimensional rectangle with the top and left sides in the
+ * color specified by inTopLeftColor and the bottom and right sides in the color
+ * specified by inBottomRightColor.
+ *
+ * @param inRect The rectangle to draw
+ * @param inTopLeftColor Color for the top and left sides of the rect
+ * @param inBottomRightColor Color for the bottom and right sides of the rect
+ */
+void CWinRenderer::Draw3dRect(const QRect &inRect, const QColor &inTopLeftColor,
+ const QColor &inBottomRightColor)
+{
+ auto rect = inRect;
+ rect.translate(m_Translation);
+ m_painter->drawRect(rect);
+ m_painter->save();
+ m_painter->setPen(inTopLeftColor);
+ m_painter->drawLine(rect.topLeft(), rect.bottomLeft());
+ m_painter->drawLine(rect.topLeft(), rect.topRight());
+ m_painter->setPen(inBottomRightColor);
+ m_painter->drawLine(rect.bottomLeft(), rect.bottomRight());
+ m_painter->drawLine(rect.bottomRight(), rect.topRight());
+ m_painter->restore();
+}
+
+//==============================================================================
+/**
+ * DrawBitmap
+ *
+ * Draw a bitmap given a device context, position and HBITMAP handle.
+ *
+ * @param inDC Device context for drawing
+ * @param inPos CPoint position for drawing
+ * @param inBitmap Handle of the bitmap to draw
+ */
+//==============================================================================
+void CWinRenderer::DrawBitmap(const QPoint &inPos, const QPixmap &inImage)
+{
+ m_painter->save();
+ m_painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+ m_painter->drawPixmap(inPos + m_Translation, inImage);
+ m_painter->restore();;
+}
+
+void CWinRenderer::PushTranslation(const QPoint &inTranslation)
+{
+ m_Translation += inTranslation;
+
+ m_Translations.push_back(inTranslation);
+}
+
+void CWinRenderer::PopTranslation()
+{
+ QPoint thePreviousTranslation = m_Translations.back();
+ m_Translation -= thePreviousTranslation;
+
+ m_Translations.pop_back();
+}
+
+QPoint CWinRenderer::GetTranslation()
+{
+ return m_Translation;
+}
+
+QPainter* CWinRenderer::GetPainter()
+{
+ return m_painter;
+}
+
+//==============================================================================
+/**
+ * Get the current clipping rect.
+ * The clipping rect is the boundary of pixels that will be drawn to the DC.
+ * This can be used to not draw non-visible objects.
+ * @return the clipping rect in local coordinates.
+ */
+QRect CWinRenderer::GetClippingRect()
+{
+ QRect theClippingRect = m_painter->clipBoundingRect().toRect();
+ theClippingRect.translate(-m_Translation);
+
+ return theClippingRect;
+}
+
+//==============================================================================
+/**
+ * Push a clipping rect onto the stack of clipping rects.
+ * This will cause any drawing outside of the clipping rect to be ignored. The
+ * Control class also uses this to not draw objects outside of this rect.
+ * @param inClippingRect the new clipping rect, in local coordinates.
+ */
+void CWinRenderer::PushClippingRect(const QRect &inClippingRect)
+{
+ QRect clippingRect(inClippingRect);
+ clippingRect.translate(m_Translation);
+
+ const QRegion currentRegion = m_painter->clipRegion();
+ m_painter->setClipRect(clippingRect);
+
+ m_ClippingRegions.push_back(currentRegion);
+}
+
+//==============================================================================
+/**
+ * Pop the current clipping rect.
+ * This will change the clipping rect to use the one previous to the current
+ * one.
+ */
+void CWinRenderer::PopClippingRect()
+{
+ if (m_ClippingRegions.size() > 1) {
+ QRegion thePreviousRegion = m_ClippingRegions.back();
+ m_painter->setClipRegion(thePreviousRegion);
+ m_ClippingRegions.pop_back();
+ }
+}
+
+//==============================================================================
+/**
+ * DrawGradiantBitmap
+ *
+ * Draws a gradiant based on the begin color
+ *
+ * @param inRct Rct tof the control
+ * @param inBeginColor color to start with
+ * @param inInverted true if this is inverted
+ */
+void CWinRenderer::DrawGradientBitmap(const QRect &inRct, const QColor &inBeginColor, bool inInverted,
+ double inScalingFactor)
+{
+ QRect rect(inRct);
+ QRect theClippingRect = GetClippingRect();
+ rect &= theClippingRect;
+ rect.translate(m_Translation);
+
+ long theHeight = rect.height();
+ long theWidth = rect.width();
+
+ QImage theCompatibleBitmap(1, theHeight, QImage::Format_RGB32);
+
+ int theR = inBeginColor.red();
+ int theG = inBeginColor.green();
+ int theB = inBeginColor.blue();
+
+ double theExtraRModifier = inScalingFactor * (1.0 - (theR / 255.0));
+ double theExtraGModifier = inScalingFactor * (1.0 - (theG / 255.0));
+ double theExtraBModifier = inScalingFactor * (1.0 - (theB / 255.0));
+
+ for (long thePixel = 0; thePixel < theHeight; ++thePixel) {
+ double theNormPixel = (double)thePixel / (theHeight * 4.8);
+ double theCos = 1.0 / (theNormPixel * theNormPixel + 1.0);
+ double theRValue = (double)theR * (theCos + theExtraRModifier);
+ double theGValue = (double)theG * (theCos + theExtraGModifier);
+ double theBValue = (double)theB * (theCos + theExtraBModifier);
+
+ QColor theTempColor(::dtoi(theRValue), ::dtoi(theGValue), ::dtoi(theBValue));
+ if (inInverted) {
+ theCompatibleBitmap.setPixelColor(0, qMax(0l, theHeight - thePixel - 2), theTempColor);
+ } else {
+ theCompatibleBitmap.setPixelColor(0, thePixel, theTempColor);
+ }
+ theExtraRModifier *= 0.3;
+ theExtraGModifier *= 0.3;
+ theExtraBModifier *= 0.3;
+ }
+
+ m_painter->save();
+ m_painter->drawImage(QRect(rect.x(), rect.y(), theWidth, theHeight), theCompatibleBitmap);
+ m_painter->restore();
+}
+
+//=============================================================================
+/**
+ * Scroll the selected area of the current view by the specified amount.
+ * This will take the rectangle represented by inVisibleSize and 'scroll' it
+ * by inAmount. The section that goes out of the visible size will be clipped
+ * off and the area entering the visible area will be empty.
+ * @param inAmount the amount to scroll by.
+ * @param inVisibleSize the rectangle to be scrolled.
+ * @return the smallest rect of area that needs to be redrawn.
+ */
+QRect CWinRenderer::Scroll(const QPoint &inAmount, const QRect &inVisibleSize)
+{
+#if KDAB_TEMPORARILY_REMOVED
+ inAmount.Offset(m_Translation);
+ inVisibleSize.Offset(m_Translation);
+
+ QRect theVisibleRect(QPoint(inVisibleSize.position.x, inVisibleSize.position.y),
+ QSize(inVisibleSize.size.x, inVisibleSize.size.y));
+
+ CRgn theDirtyRegion;
+ CRect theDirtyRect;
+ m_painter->ScrollDC(inAmount.x, inAmount.y, theVisibleRect, theVisibleRect, &theDirtyRegion,
+ &theDirtyRect);
+
+ QRect theDirtyRct(theDirtyRect.left, theDirtyRect.top, theDirtyRect.right - theDirtyRect.left,
+ theDirtyRect.bottom - theDirtyRect.top);
+
+ theDirtyRct.Offset(QPoint(-m_Translation.x, -m_Translation.y));
+
+ return theDirtyRct;
+#else
+ return {};
+#endif
+}
+
+//=============================================================================
+/**
+ * Draw a gradient over inRect.
+ * This will blend horizontally across the rect from inBeginColor into inEndColor.
+ * This does linear interpolation.
+ * @param inRect the rect to draw on.
+ * @param inBeginColor the start (left most) color.
+ * @param inEndColor the final (right most) color.
+ */
+void CWinRenderer::DrawGradient(const QRect &inRect, const QColor &inBeginColor, const QColor &inEndColor)
+{
+ const QRect rect = inRect.translated(m_Translation);
+ QLinearGradient gradient(rect.topLeft(), rect.topRight());
+ gradient.setColorAt(0, inBeginColor);
+ gradient.setColorAt(1, inEndColor);
+
+ QBrush brush(gradient);
+ m_painter->fillRect(rect, brush);
+}
+
+void CWinRenderer::FillHashed(const QRect &inRect, const QColor &inForegroundColor)
+{
+ m_painter->save();
+
+ QBrush theBrush(inForegroundColor, Qt::BDiagPattern);
+ QPen pen(inForegroundColor);
+ m_painter->setPen(pen);
+ m_painter->setBrush(theBrush);
+ m_painter->drawRect(inRect.translated(m_Translation));
+
+ m_painter->restore();
+}
+
+QPen CWinRenderer::GetPen(const QColor &inColor, int inWidth, Qt::PenStyle inStyle)
+{
+ QPen thePen;
+ SPenInfo theInfo = { inColor, inWidth, inStyle };
+ TPenMap::iterator thePos = m_Pens.find(theInfo);
+ if (thePos != m_Pens.end()) {
+ thePen = thePos->second;
+ } else {
+ thePen.setColor(inColor);
+ thePen.setWidth(inWidth);
+ m_Pens[theInfo] = thePen;
+ }
+ return thePen;
+}
+
+QPixmap CWinRenderer::pixmap() const
+{
+ return {};
+}
diff --git a/src/Authoring/Studio/_Win/Controls/WinRenderer.h b/src/Authoring/Studio/_Win/Controls/WinRenderer.h
new file mode 100644
index 00000000..4ebcc689
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/WinRenderer.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_WIN_RENDERER_H
+#define INCLUDED_WIN_RENDERER_H 1
+
+#pragma once
+
+#include <vector>
+#include <map>
+
+#include "Pt.h"
+#include "Rct.h"
+#include "Renderer.h"
+
+#include <QPainter>
+#include <QRegion>
+
+QT_BEGIN_NAMESPACE
+class QPixmap;
+QT_END_NAMESPACE
+
+class CWinRenderer : public CRenderer
+{
+ typedef std::vector<QPen> TPenList;
+ typedef std::vector<QRegion> TClippingRegions;
+
+protected:
+ CWinRenderer(); ///< Leaves CRenderer in an invalid state, only for subclasses
+ CWinRenderer(QPainter *inDC); ///< Leaves CRenderer in an invalid state, only for subclasses
+
+public:
+ CWinRenderer(QPainter *inDC, const QRect &inClippingRect);
+ virtual ~CWinRenderer();
+
+ void FillSolidRect(const QRect &inCoordinates, const QColor &inColor) override;
+
+ void MoveTo(const QPoint &inPoint) override;
+ void MoveTo(long inX, long inY) override;
+ void LineTo(const QPoint &inPoint) override;
+ void LineTo(long inX, long inY) override;
+
+ void PushPen(const QColor &inColor, int inWidth = 1) override;
+ void PopPen() override;
+ void BitBltFrom(const QRect &inRect, CRenderer *inRenderer, long inXSrc, long inYSrc) override;
+
+ void DrawText(float inX, float inY, const QString &inText) override;
+ void DrawText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingRect, const QColor &inColor = Qt::black) override;
+ void DrawBoldText(float inX, float inY, const QString &inText,
+ const QRect &inBoundingRect, const QColor &inColor = Qt::black) override;
+
+ QSize GetTextSize(const QString &inText) override;
+
+ void DrawBitmap(const QPoint &inPos, const QPixmap &inImage) override;
+ void Draw3dRect(const QRect &inRect, const QColor &inTopLeftColor,
+ const QColor &inBottomRightColor) override;
+ void DrawGradientBitmap(const QRect &inRct, const QColor &inBeginColor, bool inInverted,
+ double inScalingFactor = .99) override;
+
+ void DrawGradient(const QRect &inRect, const QColor &inBeginColor, const QColor &inEndColor) override;
+
+ void PushTranslation(const QPoint &inTranslation) override;
+ void PopTranslation() override;
+ QPoint GetTranslation() override;
+
+ QRect GetClippingRect() override;
+ void PushClippingRect(const QRect &inRect) override;
+ void PopClippingRect() override;
+ void PushAbsoluteClippingRect(const QRect &inRect) override {}
+ void FillHashed(const QRect &inRect, const QColor &inForeGroundColor) override;
+ QRect Scroll(const QPoint &inAmount, const QRect &inVisibleSize) override;
+ QPainter *GetPainter() override;
+ QPen GetPen(const QColor &inColor, int inWidth, Qt::PenStyle inStyle);
+
+ QPixmap pixmap() const override;
+
+protected:
+ TPenList m_PenList;
+ TClippingRegions m_ClippingRegions;
+ QPainter *m_painter;
+ QPoint m_currentPos;
+
+protected:
+ struct SPenInfo
+ {
+ QColor Color;
+ long Width;
+ Qt::PenStyle Style;
+ };
+
+ class CPenInfoLessThan : public std::binary_function<const SPenInfo &, const SPenInfo &, bool>
+ {
+ public:
+ inline bool operator()(const SPenInfo &inValL, const SPenInfo &inValR) const
+ {
+ return memcmp(&inValL, &inValR, sizeof(SPenInfo)) < 0;
+ }
+ };
+
+ typedef std::map<SPenInfo, QPen, CPenInfoLessThan> TPenMap;
+ TPenMap m_Pens;
+};
+#endif // INCLUDED_WIN_RENDERER_H
diff --git a/src/Authoring/Studio/_Win/Controls/WndControl.cpp b/src/Authoring/Studio/_Win/Controls/WndControl.cpp
new file mode 100644
index 00000000..c218f9b9
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/WndControl.cpp
@@ -0,0 +1,1006 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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 "stdafx.h"
+
+#include "WndControl.h"
+#include "WinRenderer.h"
+#include "Control.h"
+#include "MasterP.h"
+#include "AppFonts.h"
+#include "ContextMenu.h"
+#include "HotKeys.h"
+#include "StudioPreferences.h"
+#include "WinDnd.h"
+#include "Doc.h"
+#include "DropSource.h"
+#include "IDragable.h"
+#include "OffscreenRenderer.h"
+
+BEGIN_MESSAGE_MAP(CWndControl, CWnd)
+//{{AFX_MSG_MAP(CWndControl)
+ON_WM_KILLFOCUS()
+ON_WM_SETFOCUS()
+ON_WM_PAINT()
+ON_WM_LBUTTONUP()
+ON_WM_LBUTTONDOWN()
+ON_WM_RBUTTONDOWN()
+ON_WM_RBUTTONUP()
+ON_WM_LBUTTONDBLCLK()
+ON_WM_SIZING()
+ON_WM_ERASEBKGND()
+ON_WM_SIZE()
+ON_WM_MOUSEMOVE()
+ON_WM_CREATE()
+ON_WM_MOUSEACTIVATE()
+ON_WM_MOUSEWHEEL()
+ON_WM_CTLCOLOR()
+ON_CONTROL_REFLECT(EN_CHANGE, OnEnChange)
+//}}AFX_MSG_MAP
+ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
+ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
+END_MESSAGE_MAP()
+
+//=============================================================================
+/**
+ * Creates the pass thru class for the wnd control.
+ */
+CWndControlControlListener::CWndControlControlListener(CWndControl *inParent)
+{
+ m_Parent = inParent;
+}
+
+//=============================================================================
+/**
+ * Notification from the control that the window was invalidated.
+ */
+void CWndControlControlListener::OnControlInvalidated()
+{
+ m_Parent->OnControlInvalidated();
+}
+
+//=============================================================================
+/**
+ * Notification from the control to do a popup at the specified location.
+ */
+long CWndControlControlListener::DoPopup(CContextMenu *inContextMenu, CPt inPoint)
+{
+ return m_Parent->DoPopup(inContextMenu, inPoint);
+}
+
+//=============================================================================
+/**
+ * Get the location of the point in Screen coordinates.
+ */
+CPt CWndControlControlListener::ClientToScreen(CPt inPoint)
+{
+ CPoint thePoint(inPoint.x, inPoint.y);
+ m_Parent->ClientToScreen(&thePoint);
+
+ return CPt(thePoint.x, thePoint.y);
+}
+
+//=============================================================================
+/**
+ * Get the location of the point into client coordinates.
+ */
+CPt CWndControlControlListener::ScreenToClient(CPt inPoint)
+{
+ CPoint thePoint(inPoint.x, inPoint.y);
+ m_Parent->ScreenToClient(&thePoint);
+
+ return CPt(thePoint.x, thePoint.y);
+}
+
+//=============================================================================
+/**
+ * Get the platform dependent view that this is embedding.
+ * Used when platform dependent controls need to be embedded into the Controls.
+ */
+TPlatformView CWndControlControlListener::GetPlatformView()
+{
+ return m_Parent->m_hWnd;
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's SetIsDragging function.
+ * @param inIsDragging true to specify that a drag is occurring or false to cancel a drag
+ */
+void CWndControlControlListener::SetIsDragging(bool inIsDragging)
+{
+ m_Parent->SetIsDragging(inIsDragging);
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's ShowTooltips function.
+ * @param inLocation mid-point of the tooltip in global coordinates
+ * @param inText text to display as a tooltip
+ */
+void CWndControlControlListener::ShowTooltips(CPt inLocation, Q3DStudio::CString inText)
+{
+ m_Parent->ShowTooltips(inLocation, inText);
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's HideTooltips function.
+ */
+void CWndControlControlListener::HideTooltips()
+{
+ m_Parent->HideTooltips();
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's ShowMoveableTooltips function.
+ * @param inLocation mid-point of the tooltip in global coordinates
+ * @param inText text to display as a tooltip
+ */
+void CWndControlControlListener::ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText,
+ CRct inBoundingRct)
+{
+ m_Parent->ShowMoveableWindow(inLocation, inText, inBoundingRct);
+}
+
+//=============================================================================
+/**
+ * Pass-thru to the CWndControl's HideMoveableTooltips function.
+ */
+void CWndControlControlListener::HideMoveableWindow()
+{
+ m_Parent->HideMoveableWindow();
+}
+
+void CWndControlControlListener::DoStartDrag(IDragable *inDragable)
+{
+ m_Parent->DoStartDrag(inDragable);
+}
+
+//===============================================================================
+/**
+* performs a drag operation on a file
+*/
+void CWndControlControlListener::DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList)
+{
+ m_Parent->DoStartDrag(inDragFileNameList);
+}
+
+IMPLEMENT_OBJECT_COUNTER(CWndControl);
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CWndControl::CWndControl(CControl *inControl)
+ : m_MouseOver(false)
+ , m_MemDC(nullptr)
+ , m_IsDragging(false)
+ , m_ControlListener(this)
+ , m_IsMouseDown(false)
+{
+ ADDTO_OBJECT_COUNTER(CWndControl);
+
+ m_Control = inControl;
+
+ if (m_Control)
+ m_Control->SetWindowListener(&m_ControlListener);
+
+ RegisterWindowClass();
+
+ // Create the tooltip for this window (there's only one per view)
+ m_Tooltip.CreateEx(WS_EX_TOOLWINDOW, AfxRegisterWndClass(CS_SAVEBITS), L"CPopupWndTooltip",
+ WS_POPUP | WS_BORDER, CRect(0, 0, 20, 10), this, 0);
+ m_Tooltip.SetStationary(true);
+
+ // Create the tooltip for this window (there's only one per view)
+ m_MoveableTooltip.CreateEx(WS_EX_TOOLWINDOW, AfxRegisterWndClass(CS_SAVEBITS),
+ L"CPopupWndTooltip", WS_POPUP | WS_BORDER, CRect(0, 0, 20, 10), this,
+ 0);
+ m_MoveableTooltip.SetStationary(false);
+
+ m_Brush.CreateSolidBrush(CStudioPreferences::GetBaseColor());
+
+#ifdef _DEBUG
+ m_IsPainting = false;
+#endif
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CWndControl::~CWndControl()
+{
+ DeleteBuffers();
+
+ REMOVEFROM_OBJECT_COUNTER(CWndControl);
+}
+
+// Register the window class if it has not already been registered.
+BOOL CWndControl::RegisterWindowClass()
+{
+ WNDCLASS wndcls;
+ HINSTANCE hInst = AfxGetInstanceHandle();
+
+ if (!(::GetClassInfo(hInst, WNDCONTROL_CLASSNAME, &wndcls))) {
+ // otherwise we need to register a new class
+ wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
+ wndcls.lpfnWndProc = ::DefWindowProc;
+ wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
+ wndcls.hInstance = hInst;
+ wndcls.hIcon = nullptr;
+ wndcls.hCursor = nullptr;
+ wndcls.hbrBackground = m_Brush;
+ wndcls.lpszMenuName = nullptr;
+ wndcls.lpszClassName = WNDCONTROL_CLASSNAME;
+
+ if (!AfxRegisterClass(&wndcls)) {
+ AfxThrowResourceException();
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * Create: Handles the WM_CREATE message.
+ *
+ * Creates the view, sets the font, and loads the toolbar.
+ *
+ * @param lpszClassName Names the Windows class. The class name can be any name
+ *registered with the AfxRegisterWndClass
+ * @param lpszWindowName Represents the window name. Used as text for the title bar.
+ * @param dwStyle Specifies the window style attributes.
+ * @param rect Specifies the size and position of the window.
+ * @param pParentWnd Pointer to the parent of the view.
+ * @param nID The ID for the view.
+ * @param pContext Create context for the view.
+ *
+ * @return TRUE if creation was successful, otherwise FALSE.
+ */
+//==============================================================================
+int CWndControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ return CWnd::OnCreate(lpCreateStruct);
+}
+
+//=============================================================================
+/**
+ * MFC notification that this window needs to be redrawn.
+ * This buffers the draw DC, makes a Renderer and has the Control draw to the
+ * buffered DC.
+ */
+void CWndControl::OnPaint()
+{
+#ifdef _DEBUG
+ m_IsPainting = true;
+#endif
+
+ UICPROFILE(OnPaint);
+
+ CPaintDC dc(this);
+
+ HDC theDeviceContext = dc.GetSafeHdc();
+
+ RECT theSize;
+ this->GetClientRect(&theSize);
+
+ bool theRedrawAllFlag = false;
+
+ if (m_MemDC == nullptr) {
+ m_MemDC = new CDC();
+ m_MemDC->CreateCompatibleDC(&dc);
+ m_MemDC->SelectObject(CAppFonts::GetInstance()->GetNormalFont());
+
+ m_MemBitmap = ::CreateCompatibleBitmap(theDeviceContext, theSize.right, theSize.bottom);
+
+ m_OldBitmap = (HBITMAP)m_MemDC->SelectObject(m_MemBitmap);
+
+ theRedrawAllFlag = true;
+ }
+
+ CRct theDirtyRect;
+ {
+ UICPROFILE(OnPaint_Render);
+ CWinRenderer theRenderer(m_MemDC, CRct(0, 0, theSize.right, theSize.bottom));
+ if (m_Control)
+ m_Control->OnDraw(&theRenderer, theDirtyRect, theRedrawAllFlag);
+ }
+
+ // Copy (BitBlt) bitmap from bitmap memory DC to memory DC
+ // ::BitBlt( theDeviceContext, theDirtyRect.position.x, theDirtyRect.position.y,
+ //theDirtyRect.size.x, theDirtyRect.size.y, m_MemDC->GetSafeHdc( ), theDirtyRect.position.x,
+ //theDirtyRect.position.y, SRCCOPY );
+ ::BitBlt(theDeviceContext, 0, 0, theSize.right, theSize.bottom, m_MemDC->GetSafeHdc(), 0, 0,
+ SRCCOPY);
+
+#ifdef _DEBUG
+ m_IsPainting = false;
+#endif
+}
+
+void CWndControl::DeleteBuffers()
+{
+ if (m_MemDC != nullptr) {
+ m_MemDC->SelectObject(m_OldBitmap);
+ ::DeleteObject(m_MemBitmap);
+ m_MemDC->DeleteDC();
+ delete m_MemDC;
+ m_MemDC = nullptr;
+ }
+}
+
+//=============================================================================
+/**
+ * Notification to this window that it has lost focus.
+ * @param pNewWnd the window that has gained focus.
+ */
+void CWndControl::OnKillFocus(CWnd *pNewWnd)
+{
+ CWnd::OnKillFocus(pNewWnd);
+
+ // This is used for special cases where we lose control of the mouse and lose focus as well.
+ // It makes sure we are not still receiving mouse messages.
+ if (m_IsMouseDown) {
+ // Tell the control that it got a mouse up
+ if (m_Control)
+ m_Control->OnMouseUp(CPt(-1, -1), CHotKeys::GetCurrentKeyModifiers());
+ ReleaseCapture();
+ }
+
+ if (m_Control) {
+ // For the case where pNewWnd is an "embedded" control in m_Control (eg.
+ // CPlatformEditControl)
+ // m_Control should not lose focus.
+ // Note that since most of the Studio controls uses a common PlatformDevice (the Studio
+ // window),
+ // this (OnKillFocus) only occurs when 1) switching to another app, 2) popping up a dialog
+ // box or 3) an embedded control
+ // takes focus.
+ // This takes care of the case when an embedded control takes focus but unwittingly causes
+ // its parent to lose focus.
+ // This can have dire consequences if the parent control were to do something on losing
+ // focus, such as
+ // destroying all its children. For example, Bug3421.
+ if (!m_Control->IsChildPlatformDevice(pNewWnd->GetSafeHwnd()))
+ m_Control->OnLoseFocus();
+ }
+}
+
+void CWndControl::OnSetFocus(CWnd *pPrevWnd)
+{
+ CWnd::OnSetFocus(pPrevWnd);
+ if (m_Control)
+ m_Control->OnGainFocus();
+}
+
+//=============================================================================
+/**
+ * Notification of mouse up.
+ */
+void CWndControl::OnLButtonUp(UINT nFlags, CPoint inPoint)
+{
+ Q_UNUSED(nFlags);
+ m_IsMouseDown = false;
+ // Tell the control that it got a mouse up
+ if (m_Control)
+ m_Control->OnMouseUp(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers());
+
+ ReleaseCapture();
+
+ CWnd::OnLButtonUp(nFlags, inPoint);
+}
+
+//=============================================================================
+/**
+ * Notification of a mouse click.
+ */
+void CWndControl::OnLButtonDown(UINT nFlags, CPoint inPoint)
+{
+ Q_UNUSED(nFlags);
+ m_IsMouseDown = true;
+ SetCapture();
+ // Tell the control that it got a mouse down.
+ if (m_Control)
+ m_Control->OnMouseDown(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers());
+
+ CWnd::OnLButtonDown(nFlags, inPoint);
+}
+
+//=============================================================================
+/**
+ * Notification of a mouse click.
+ */
+void CWndControl::OnRButtonDown(UINT nFlags, CPoint inPoint)
+{
+ SetCapture();
+
+ if (m_IsMouseDown) {
+ // Tell the control that it got a mouse up
+ if (m_Control)
+ m_Control->OnMouseUp(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers());
+ m_IsMouseDown = false;
+ }
+
+ // Tell the control that it got a mouse down.
+ if (m_Control)
+ m_Control->OnMouseRDown(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers());
+
+ CWnd::OnRButtonDown(nFlags, inPoint);
+}
+
+//=============================================================================
+/**
+ * Notification of mouse up.
+ */
+void CWndControl::OnRButtonUp(UINT nFlags, CPoint inPoint)
+{
+ Q_UNUSED(nFlags);
+
+ // Tell the control that it got a mouse up
+ if (m_Control)
+ m_Control->OnMouseRUp(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers());
+
+ ReleaseCapture();
+}
+
+long CWndControl::DoPopup(CContextMenu *inMenu, CPt inPoint)
+{
+ CPoint thePoint(inPoint.x, inPoint.y);
+ ClientToScreen(&thePoint);
+
+ long theSelectedItem = inMenu->DoPopup(CPt(thePoint.x, thePoint.y), m_hWnd);
+ if (m_IsMouseDown) {
+ m_IsMouseDown = false;
+ if (m_Control)
+ m_Control->OnMouseUp(CPt(-1, -1), 0);
+ }
+ ReleaseCapture();
+
+ return theSelectedItem;
+}
+
+//=============================================================================
+/**
+ * Notification of a mouse double click.
+ */
+void CWndControl::OnLButtonDblClk(UINT nFlags, CPoint inPoint)
+{
+ Q_UNUSED(nFlags);
+
+ // Tell the control that it got a mouse down.
+ if (m_Control)
+ m_Control->OnMouseDoubleClick(CPt(inPoint.x, inPoint.y), nFlags);
+}
+
+//=============================================================================
+/**
+ * Notification of a key down message.
+ */
+bool CWndControl::OnKeyDown(UINT inChar, UINT, UINT)
+{
+ return m_Control->OnKeyDown(inChar, CHotKeys::GetCurrentKeyModifiers());
+}
+
+//=============================================================================
+/**
+ * Notification of a key up messages. May be hooked up later.
+ */
+bool CWndControl::OnKeyUp(UINT inChar, UINT, UINT)
+{
+ return m_Control->OnKeyUp(inChar, CHotKeys::GetCurrentKeyModifiers());
+}
+
+//=============================================================================
+/**
+ * Notification of a character press message.
+ *
+ * @return true if the character was processed by the control, otherwise false
+ */
+bool CWndControl::OnChar(UINT inChar, UINT, UINT)
+{
+ return m_Control->OnChar(inChar, CHotKeys::GetCurrentKeyModifiers());
+}
+
+//=============================================================================
+/**
+ * Displays a tooltip at the desired location, and with the desired text.
+ * @param inLocation mid-point of the tooltext message box to be displayed
+ * @param inText text to be displayed as the tooltip
+ */
+void CWndControl::ShowTooltips(CPt inLocation, Q3DStudio::CString inText)
+{
+ // If the global preference for tooltips is enabled
+ if (CStudioPreferences::ShouldShowTooltips()) {
+ // If the tooltip text is not empty, show the tooltip
+ if (!inText.IsEmpty()) {
+ // So that tooltip text renders within the window
+ // this would be nicely taken care of if this were a MFC control...
+ COffscreenRenderer theOffscreenRenderer(CRct(0, 0, 1, 1));
+ float theWidth(0);
+ float theHeight(0);
+ theOffscreenRenderer.GetTextSize(inText, theWidth, theHeight);
+
+ long theRightMargin = m_Control->GetPosition().x + m_Control->GetSize().x;
+ if (inLocation.x + ::dtol(theWidth) > theRightMargin) // re-centers this
+ inLocation.x = theRightMargin - ::dtol(theWidth) / 2;
+
+ // Convert the point to screen coordinates
+ ::CPoint theScreenCoords = ::CPoint(inLocation.x, inLocation.y);
+ ClientToScreen(&theScreenCoords);
+ m_Tooltip.UpdateToolTip(theScreenCoords, ::CString(inText.GetMulti()), true);
+ }
+ // If the tooltip text is empty, hide the tooltip
+ else
+ m_Tooltip.ShowWindow(SW_HIDE);
+ }
+}
+
+//=============================================================================
+/**
+ * Hides any tooltip currently being displayed.
+ */
+void CWndControl::HideTooltips()
+{
+ m_Tooltip.ShowWindow(SW_HIDE);
+}
+
+//=============================================================================
+/**
+ * Starts the Dragging process.
+ * On the given IDragable.
+ * @param inAsset the Asset to be drug.
+ */
+void CWndControl::DoStartDrag(IDragable *inDragable)
+{
+ // Tell the window that we are beginning a drag
+ if (inDragable && !m_IsDragging) {
+ // This should prevent the Container from dragging while it is already dragging.
+ SetIsDragging(true);
+
+ // This is a Wrapper for the OLEDROP
+ CWinDragManager theDragManager;
+
+ // Theoretically: there is no limit to the amount of data you can add.
+ // For now only one object will work, until i figure out how to drag multiple objects in
+ // windows.
+ Q3DStudio::CAutoMemPtr<CDropSource> theDropSource =
+ CDropSourceFactory::Create(inDragable->GetFlavor(), inDragable);
+
+ // Add the UIC_GESTURE_FLAVOR. This will allow us to drag to StudioControls.
+ theDragManager.AddData(inDragable->GetFlavor(), &theDropSource, sizeof(CDropSource *));
+ // This is a blocking call when we get done with this call we should have no more data in
+ // our Drag list.
+ theDragManager.StartDrag();
+
+ // Tell the window that we are done dragging
+ SetIsDragging(false);
+ }
+}
+
+//===============================================================================
+/**
+* performs a drag operation on a file
+*/
+void CWndControl::DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList)
+{
+ // Tell the window that we are beginning a drag
+ if (!m_IsDragging) {
+ SetIsDragging(true);
+
+ try {
+ CWinDragManager theDragManager;
+
+ std::vector<Q3DStudio::CString>::iterator thePos = inDragFileNameList.begin();
+ std::vector<Q3DStudio::CString>::iterator theEndPos = inDragFileNameList.end();
+
+ Q3DStudio::CAutoMemPtr<CDropSource> theDropSource;
+ Q3DStudio::CAutoMemPtr<CUICFile> theDragFile;
+ for (; thePos != theEndPos; ++thePos) {
+ Q3DStudio::CString theDragFileName = *thePos;
+ if (theDragFileName.Length() > 0) {
+ theDragFile = new CUICFile(theDragFileName);
+ theDropSource = CDropSourceFactory::Create(
+ EUIC_FLAVOR_ASSET_UICFILE, (void *)theDragFile, sizeof(theDragFile));
+ // Add the UIC_GESTURE_FLAVOR. This will allow us to drag to StudioControls.
+ theDragManager.AddData(EUIC_FLAVOR_ASSET_UICFILE, &theDropSource,
+ sizeof(CDropSource *));
+ break;
+ }
+ }
+ theDragManager.StartDrag();
+ } catch (...) { // if there are any errors that throws an exception, there
+ // there will be no more drag and drop, since the flag will not be reset.
+ }
+ // Tell the window that we are done dragging
+ SetIsDragging(false);
+ }
+}
+
+//=============================================================================
+/**
+ * Notification of a mouse wheel movement.
+ */
+BOOL CWndControl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
+{
+ ScreenToClient(&pt);
+ if (m_Control)
+ m_Control->OnMouseWheel(CPt(pt.x, pt.y), zDelta, CHotKeys::GetCurrentKeyModifiers());
+
+ //Q_UNUSED( nFlags );
+ //Q_UNUSED( zDelta );
+ //Q_UNUSED( pt );
+ return CWnd::OnMouseWheel(nFlags, zDelta, pt);
+}
+
+LRESULT CWndControl::OnRegisteredMouseWheel(WPARAM, LPARAM)
+{
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Notification that this window is being resized.
+ */
+void CWndControl::OnSizing(UINT nSide, LPRECT lpRect)
+{
+ Q_UNUSED(nSide);
+ Q_UNUSED(lpRect);
+}
+
+//=============================================================================
+/**
+ * Override of erase to prevent flashing of the background.
+ */
+BOOL CWndControl::OnEraseBkgnd(CDC *pDC)
+{
+ Q_UNUSED(pDC);
+ return FALSE;
+}
+
+//=============================================================================
+/**
+ * Notification that this window has been resized.
+ */
+void CWndControl::OnSize(UINT nType, int cx, int cy)
+{
+ CWnd::OnSize(nType, cx, cy);
+
+ MoveWindow(0, 0, cx, cy);
+
+ CRect theSize;
+ GetClientRect(&theSize);
+
+ if (m_Control)
+ m_Control->SetSize(CPt(theSize.right, theSize.bottom));
+
+ // Gotta recreate the buffered objects, otherwise they will be the wrong dimensions
+ DeleteBuffers();
+}
+
+//=============================================================================
+/**
+ * Event notification that the mouse has moved.
+ */
+void CWndControl::OnMouseMove(UINT, CPoint point)
+{
+#ifdef _DEBUG
+ m_IsPainting = true;
+#endif
+
+ UICPROFILE(OnMouseMove);
+
+ // Track the mouse while it's in here, this will give us the hover msg
+ m_MouseOver = true;
+
+ TRACKMOUSEEVENT theEventStruct;
+ theEventStruct.cbSize = sizeof(TRACKMOUSEEVENT);
+ theEventStruct.dwFlags = TME_HOVER | TME_LEAVE;
+ theEventStruct.hwndTrack = GetSafeHwnd();
+ theEventStruct.dwHoverTime = HOVER_DEFAULT;
+
+ ::TrackMouseEvent(&theEventStruct);
+
+ // Notify the control that the mouse moved
+ if (m_Control) {
+ m_Control->OnMouseMove(CPt(point.x, point.y), CHotKeys::GetCurrentKeyModifiers());
+
+ // If the control invalidated because of a mouse event then we want to do an immediate
+ // redraw.
+ // this ensures consistent visible feedback.
+ if (m_Control->IsChildInvalidated()) {
+ UICPROFILE(RedrawWindow);
+ RedrawWindow(nullptr, nullptr, RDW_UPDATENOW);
+ }
+ }
+
+#ifdef _DEBUG
+ m_IsPainting = false;
+#endif
+}
+
+//=============================================================================
+/**
+ * Notification that the mouse has left this window.
+ */
+LRESULT CWndControl::OnMouseLeave(WPARAM inwParam, LPARAM inlParam)
+{
+#ifdef _DEBUG
+ if (!m_IsPainting) {
+#endif _DEBUG
+
+ Q_UNUSED(inwParam);
+ Q_UNUSED(inlParam);
+
+ CPoint thePoint;
+
+ ::GetCursorPos(&thePoint);
+
+ // This will tell me what window is under this point.
+ HWND theWindow = ::WindowFromPoint(thePoint);
+
+ if (theWindow != m_hWnd) {
+ m_MouseOver = false;
+ if (m_Control)
+ m_Control->OnMouseMove(CPt(-1, -1), 0);
+ }
+
+#ifdef _DEBUG
+ }
+#endif
+
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Override to provide the hover message to the control.
+ */
+LRESULT CWndControl::OnMouseHover(WPARAM inwParam, LPARAM inlParam)
+{
+
+ long theX = inlParam & 0xFFFF;
+ long theY = (inlParam >> 16) & 0xFFFF;
+
+ if (m_Control)
+ m_Control->OnMouseHover(CPt(theX, theY), (UINT)inwParam);
+
+ TRACKMOUSEEVENT theEventStruct;
+ theEventStruct.cbSize = sizeof(TRACKMOUSEEVENT);
+ theEventStruct.dwFlags = TME_HOVER | TME_LEAVE;
+ theEventStruct.hwndTrack = GetSafeHwnd();
+ theEventStruct.dwHoverTime = HOVER_DEFAULT;
+
+ ::TrackMouseEvent(&theEventStruct);
+
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Callback from the control that it has been invalidated.
+ * This will post a message for a redraw.
+ */
+void CWndControl::OnControlInvalidated()
+{
+ if (::IsWindow(m_hWnd)) {
+ Invalidate();
+ ::PostMessage(m_hWnd, WM_PAINT, 0, 0);
+ }
+}
+
+//=============================================================================
+/**
+ * Override of PreTranslateMessage for dragging implementation.
+ */
+BOOL CWndControl::PreTranslateMessage(MSG *inMessage)
+{
+ BOOL theReturn = FALSE;
+
+ switch (inMessage->message) {
+ case WM_KEYDOWN: {
+ theReturn =
+ OnKeyDown((UINT)inMessage->wParam, inMessage->lParam & 0xFFFF, (UINT)inMessage->lParam);
+
+ BYTE theKeyboardState[256];
+ ::GetKeyboardState(theKeyboardState);
+
+ theKeyboardState[VK_CONTROL] = 0;
+
+ WORD theChar = 0;
+ // Get the ascii character for the VK key.
+ ::ToAscii((UINT)inMessage->wParam, (inMessage->lParam >> 16) & 0xFF, theKeyboardState,
+ &theChar, 0);
+ unsigned int theCharacterCode = (char)theChar;
+
+ if (theCharacterCode != 0) {
+ theReturn = theReturn
+ || OnChar(theCharacterCode, inMessage->lParam & 0xFFFF, (UINT)inMessage->lParam);
+ }
+ } break;
+
+ case WM_KEYUP:
+ // Do the OnKeyUp
+ theReturn =
+ OnKeyUp((UINT)inMessage->wParam, inMessage->lParam & 0xFFFF, (UINT)inMessage->lParam);
+ break;
+
+ case WM_CHAR:
+ theReturn = OnChar((UINT)inMessage->wParam, 0, 0);
+ break;
+
+ default:
+ break;
+ }
+
+ return theReturn;
+}
+
+//=============================================================================
+/**
+ * Call this function to indicate that a drag operation is currently taking
+ * place or has just finished. If the drag operation just finished, a mouse up
+ * event will be sent to all children so that the one who initiated the drag
+ * can clean things up.
+ * @param inIsDragging true to specify that a drag is occurring or false if a drag ended
+ */
+void CWndControl::SetIsDragging(bool inIsDragging)
+{
+ m_IsDragging = inIsDragging;
+
+ // If we are no longer dragging, notify the children that a mouse up occurred since OLE won't
+ // tell us that
+ if (!m_IsDragging)
+ m_Control->OnMouseUp(CPt(-1, -1), 0);
+}
+
+//=============================================================================
+/**
+ * Override of MouseActivate to set the focus on this.
+ */
+int CWndControl::OnMouseActivate(CWnd *pDesktopWnd, UINT nHitTest, UINT message)
+{
+ CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
+ SetFocus();
+ m_Control->OnGainFocus();
+ return MA_ACTIVATE;
+}
+
+bool CWndControl::OnDragWithin(CDropSource &inSource)
+{
+ bool theReturn = false;
+ CPt thePoint = inSource.GetCurrentPoint();
+ long theFlags = inSource.GetCurrentFlags();
+ CDropTarget *theDropTarget = m_Control->FindDropCandidate(thePoint, theFlags);
+
+ if (theDropTarget) {
+ theReturn = theDropTarget->Accept(inSource);
+ delete theDropTarget;
+ }
+ return theReturn;
+}
+
+bool CWndControl::OnDragReceive(CDropSource &inSource)
+{
+ bool theReturn = false;
+ CPt thePoint = inSource.GetCurrentPoint();
+ long theFlags = inSource.GetCurrentFlags();
+
+ CDropTarget *theDropTarget = m_Control->FindDropCandidate(thePoint, theFlags);
+
+ if (theDropTarget) {
+ theReturn = theDropTarget->Drop(inSource);
+ delete theDropTarget;
+ }
+ return theReturn;
+}
+
+void CWndControl::OnDragLeave()
+{
+ m_MouseOver = false;
+ m_Control->OnMouseMove(CPt(-1, -1), 0);
+}
+
+void CWndControl::OnReflectMouse(CPt &inPoint, long inFlags)
+{
+ // Notify the control that the mouse moved
+ m_Control->OnMouseMove(inPoint, inFlags /*CHotKeys::GetCurrentKeyModifiers( )*/);
+
+ // If the control invalidated because of a mouse event then we want to do an immediate redraw.
+ // this ensures consistent visible feedback.
+ if (m_Control->IsChildInvalidated()) {
+ UICPROFILE(RedrawWindow);
+ RedrawWindow(nullptr, nullptr, RDW_UPDATENOW);
+ }
+}
+
+void CWndControl::ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, CRct inBoundingRct)
+{
+ // If the global preference for tooltips is enabled
+ if (CStudioPreferences::ShouldShowTooltips()) {
+ // This flag is set when the control is created, it tells itself that things should
+ // not move around outside its boundaries.
+ if (inLocation.x < inBoundingRct.position.x)
+ inLocation.x = inBoundingRct.position.x;
+ if (inLocation.y < inBoundingRct.position.y)
+ inLocation.y = inBoundingRct.position.y;
+ if (inLocation.x > (inBoundingRct.position.x + inBoundingRct.size.x))
+ inLocation.x = inBoundingRct.position.x + inBoundingRct.size.x;
+ if (inLocation.y > (inBoundingRct.position.y + inBoundingRct.size.y))
+ inLocation.y = inBoundingRct.position.y + inBoundingRct.size.y;
+
+ // Convert the point to screen coordinates
+ ::CPoint theScreenCoords = ::CPoint(inLocation.x, inLocation.y);
+ ClientToScreen(&theScreenCoords);
+ // If the tooltip text is not empty, show the tooltip
+ if (!inText.IsEmpty())
+ m_MoveableTooltip.UpdateToolTip(theScreenCoords, ::CString(inText.GetMulti()), true);
+ // If the tooltip text is empty, hide the tooltip
+ else
+ m_MoveableTooltip.ShowWindow(SW_HIDE);
+ }
+}
+
+void CWndControl::HideMoveableWindow()
+{
+ m_MoveableTooltip.ShowWindow(SW_HIDE);
+}
+
+//=============================================================================
+/**
+ * Override of OnCtlColor( ) to provide a callback when the dialog is closed.
+ */
+HBRUSH CWndControl::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor)
+{
+ // Call the base class implementation first! Otherwise, it may undo what we are trying to
+ // accomplish here.
+ HBRUSH hbr = CWnd::OnCtlColor(pDC, pWnd, nCtlColor);
+
+ // Set the text color to red.
+ // pDC->SetTextColor(RGB(255, 0, 0));
+
+ // pDC->SetBkColor( CStudioPreferences::GetBaseColor( ) );
+
+ // Return handle to our CBrush object.
+ // hbr = m_Brush;
+
+ return hbr;
+}
+
+//=============================================================================
+/**
+ * Override of EN_CHANGE
+ */
+void CWndControl::OnEnChange()
+{
+}
diff --git a/src/Authoring/Studio/_Win/Controls/WndControl.h b/src/Authoring/Studio/_Win/Controls/WndControl.h
new file mode 100644
index 00000000..a7e3c72a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Controls/WndControl.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_WND_CONTROL_H
+#define INCLUDED_WND_CONTROL_H 1
+
+#pragma once
+
+#include "Control.h"
+#include "PopupWnd.h"
+#include "DropContainer.h"
+
+#define WNDCONTROL_CLASSNAME _T("WNDCONTROL")
+
+class CWndControl;
+class IDragable;
+
+class CWndControlControlListener : public CControlWindowListener
+{
+public:
+ CWndControlControlListener(CWndControl *inParent);
+ virtual void OnControlInvalidated();
+ virtual long DoPopup(CContextMenu *inMenu, CPt inLocation);
+ virtual CPt ClientToScreen(CPt inPoint);
+ virtual CPt ScreenToClient(CPt inPoint);
+ virtual TPlatformView GetPlatformView();
+ virtual void SetIsDragging(bool inIsDragging);
+ virtual void ShowTooltips(CPt inLocation, Q3DStudio::CString inText);
+ virtual void HideTooltips();
+ virtual void DoStartDrag(IDragable *inDragable);
+ virtual void DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList);
+ virtual void ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, CRct inBoundingRct);
+ virtual void HideMoveableWindow();
+
+protected:
+ CWndControl *m_Parent;
+};
+
+class CWndControl : public CWnd, public CWinDropContainer
+{
+
+public:
+ CWndControl(CControl *inAgent);
+ virtual ~CWndControl();
+
+ DEFINE_OBJECT_COUNTER(CWndControl)
+
+ BOOL RegisterWindowClass();
+
+ virtual void OnControlInvalidated();
+ long DoPopup(CContextMenu *inMenu, CPt inLocation);
+ void SetIsDragging(bool inIsDragging);
+ void DeleteBuffers();
+ bool OnKeyDown(UINT inChar, UINT inRepCnt, UINT inFlags);
+ bool OnKeyUp(UINT inChar, UINT inRepCnt, UINT inFlags);
+ bool OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+ void ShowTooltips(CPt inLocation, Q3DStudio::CString inText);
+ void HideTooltips();
+ void DoStartDrag(IDragable *inDragable);
+ void DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList);
+ virtual void ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, CRct inBoundingRct);
+ virtual void HideMoveableWindow();
+
+ bool OnDragWithin(CDropSource &inSource);
+ bool OnDragReceive(CDropSource &inSource);
+ void OnDragLeave();
+ void OnReflectMouse(CPt &inPoint, long inFlags);
+
+ //{{AFX_MSG(CWndControl)
+ afx_msg void OnKillFocus(CWnd *pNewWnd);
+ afx_msg void OnSetFocus(CWnd *pOldWnd);
+ afx_msg void OnPaint();
+ afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
+ afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
+ afx_msg void OnSizing(UINT nFlags, LPRECT pRect);
+ afx_msg BOOL OnEraseBkgnd(CDC *pDC);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg LRESULT OnRegisteredMouseWheel(WPARAM wParam, LPARAM lParam);
+ afx_msg int OnMouseActivate(CWnd *pDesktopWnd, UINT nHitTest, UINT message);
+ afx_msg HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor);
+ afx_msg void OnEnChange();
+ //}}AFX_MSG
+
+ afx_msg LRESULT OnMouseLeave(WPARAM inwParam, LPARAM inlParam);
+ afx_msg LRESULT OnMouseHover(WPARAM inwParam, LPARAM inlParam);
+ DECLARE_MESSAGE_MAP()
+protected:
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CLibraryView)
+public:
+protected:
+ virtual BOOL PreTranslateMessage(MSG *pMsg);
+ //}}AFX_VIRTUAL
+
+ CControl *m_Control;
+ CControl *m_Focus;
+ CPopupWnd m_Tooltip;
+ CPopupWnd m_MoveableTooltip;
+ CBrush m_Brush;
+ bool m_MouseOver;
+ CDC *m_MemDC;
+ HBITMAP m_MemBitmap;
+ HBITMAP m_OldBitmap;
+ bool m_IsMouseDown; /// This is used for a hack to make controls get a mouse up when we lose
+ /// focuse and
+/// the mouse is down... say we try and delete a layer while dragging and it is the last layer
+
+#ifdef _DEBUG
+ bool m_IsPainting;
+#endif
+ bool m_IsDragging;
+ CWndControlControlListener m_ControlListener;
+};
+
+#endif // INCLUDED_WND_CONTROL_H
diff --git a/src/Authoring/Studio/_Win/DragNDrop/DropProxy.cpp b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.cpp
new file mode 100644
index 00000000..ac835c00
--- /dev/null
+++ b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.cpp
@@ -0,0 +1,341 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "HotKeys.h"
+#include "DropProxy.h"
+#include "DropContainer.h"
+#include "DropSource.h"
+#include "UICFile.h"
+#include "UICString.h"
+#include "IDragable.h"
+
+#include <QDragEnterEvent>
+#include <QWidget>
+
+//=============================================================================
+/**
+ * Constructor
+ * @param inParent gesture listener that messages will be passed to
+ */
+CDropProxy::CDropProxy(CDropContainer *inParent)
+{
+ m_Parent = inParent;
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CDropProxy::~CDropProxy()
+{
+}
+
+//=============================================================================
+/**
+ * Called when a drag begins over a window.
+ */
+void CDropProxy::dragEnterEvent(QDragEnterEvent *event)
+{
+ event->ignore();
+ if (GetDragItemCount(event->mimeData())) {
+ CDropContainer::TFlavorItr theItr = m_Parent->GetFlavorBegin();
+ CDropContainer::TFlavorItr theEnd = m_Parent->GetFlavorEnd();
+
+ for (; theItr != theEnd; ++theItr) {
+ if (HasMainFlavor(event->mimeData(), *theItr)) {
+ event->accept();
+ event->setDropAction(Qt::CopyAction);
+ break;
+ }
+ }
+ }
+}
+
+//===============================================================================
+/**
+ * This will extract the Data from the OLEDropObject and convert it to a CDropSource.
+ * @param inDataObject the Win specific dropSource.
+ * @param inFlavor the Flavor we need.
+ * @param inItem the position of the data in the DataObject.
+ * @return Newly extracted or created DropSource.
+ * Note: if we created it we need to make sure we destroy this object.
+ */
+CDropSource *CDropProxy::GetDropSource(const QMimeData *inDataObject, long inFlavor, long inItem)
+{
+ const CDropSource *theDropSource = nullptr;
+ switch (inFlavor) {
+ case EUIC_FLAVOR_FILE: {
+ // Check if we have a Drop File on our hands.
+ if (inDataObject->hasUrls()) {
+ // Get the number of files being dragged
+ short theFileCount = inDataObject->urls().count();
+
+ // Only allow single files to be dragged
+ if (theFileCount > inItem && !inDataObject->urls().isEmpty()) {
+ // Get the filename of the object being dragged
+ QString theFilename = inDataObject->urls().at(inItem).toLocalFile();
+
+ CUICFile theFile(Q3DStudio::CString::fromQString(theFilename));
+ // Dragging a single file
+ theDropSource =
+ CDropSourceFactory::Create(EUIC_FLAVOR_FILE, &theFile, sizeof(CUICFile *));
+ }
+ }
+ } break;
+ case EUIC_FLAVOR_TEXT:
+ // Don't do anythiing for this
+ case EUIC_FLAVOR_LISTBOX:
+ // Don't do anythiing for this
+ case EUIC_FLAVOR_BASIC_OBJECTS:
+ // Don't do anythiing for this
+ case EUIC_FLAVOR_ASSET_LIB:
+ // make an Aset out of this.
+ case EUIC_FLAVOR_ASSET_TL:
+ // make an Aset out of this.
+ case EUIC_FLAVOR_ASSET_UICFILE:
+ // make an Aset out of this.
+ // Get a pointer to the object
+ theDropSource = dynamic_cast<const CDropSource *>(inDataObject);
+ if (theDropSource != nullptr && theDropSource->GetFlavor() != inFlavor)
+ theDropSource = nullptr;
+ break;
+ }
+ return const_cast<CDropSource *>(theDropSource);
+}
+
+//===============================================================================
+/**
+ * This is to count the number of objects in the DataObject.
+ * @param inDataObject the WinSpecific dropobject
+ * @return The number of items found.
+ */
+long CDropProxy::GetDragItemCount(const QMimeData *inDataObject)
+{
+ long theCount = 0;
+
+ // Check if we have a Drop File on our hands.
+ if (inDataObject->hasUrls()) {
+ // Get the number of files being dragged
+ theCount = inDataObject->urls().count();
+ } else {
+ auto source = dynamic_cast<const CDropSource *>(inDataObject);
+ theCount = source != nullptr ? 1 : 0;
+ }
+
+ return theCount;
+}
+//===============================================================================
+/**
+ * This will check the DataObject for the Flavor.
+ * @param inDataObject the Win specific data object.
+ * @param inFlavor the requested Flavor.
+ * @param true if the DataObject contains the flavor.
+ */
+bool CDropProxy::HasMainFlavor(const QMimeData *inDataObject, long inFlavor)
+{
+ if (inFlavor == EUIC_FLAVOR_FILE)
+ return inDataObject->hasUrls();
+ auto source = dynamic_cast<const CDropSource *>(inDataObject);
+ return source != nullptr && source->GetFlavor() == inFlavor;
+}
+
+//=============================================================================
+/**
+ * Called when a drag event leaves the window. May cause the drag to end if
+ * the mouse button is no longer down.
+ */
+void CDropProxy::dragLeaveEvent(QDragLeaveEvent *event)
+{
+ if (m_Parent) {
+ m_Parent->OnDragLeave();
+ event->accept();
+ }
+}
+
+//=============================================================================
+/**
+ * Called when an item is being dragged over this window. Passes the message
+ * on to the gesture listener.
+ */
+void CDropProxy::dragMoveEvent(QDragMoveEvent *event)
+{
+ bool theAcceptFlag = false;
+
+ if (m_Parent) {
+ long theCount = GetDragItemCount(event->mimeData());
+ for (long theIndex = 0; theIndex < theCount; ++theIndex) {
+ Qt::KeyboardModifiers theModifyerFlags = ReflectMouse(event->pos().x(), event->pos().y());
+
+ CDropContainer::TFlavorItr theItr = m_Parent->GetFlavorBegin();
+ CDropContainer::TFlavorItr theEnd = m_Parent->GetFlavorEnd();
+
+ for (; theItr != theEnd; ++theItr) {
+ // Find the Flavor of this Item.
+ if (HasMainFlavor(event->mimeData(), *theItr)) {
+ CDropSource *theDropSource = GetDropSource(event->mimeData(), *theItr, theIndex);
+ if (theDropSource) {
+ CPt thePoint(event->pos());
+ theModifyerFlags = CHotKeys::GetCurrentKeyModifiers();
+ theDropSource->SetCurrentPoint(thePoint);
+ theDropSource->SetCurrentFlags(theModifyerFlags);
+
+ theDropSource->InterpretKeyFlags(theModifyerFlags);
+ // This will be implemented in the cross platform code.
+ theAcceptFlag = m_Parent->OnDragWithin(*theDropSource);
+ event->setAccepted(theAcceptFlag);
+ if (theAcceptFlag) {
+ if (theDropSource->CanCopy())
+ event->setDropAction(Qt::CopyAction);
+ else
+ event->setDropAction(Qt::MoveAction);
+ // Breakout of the outer loop.
+ theIndex = theCount;
+ }
+
+ // delete the drop source if it was a file
+ if (EUIC_FLAVOR_FILE == theDropSource->GetFlavor()) {
+ delete theDropSource;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+//=============================================================================
+/**
+ * Called when an OLE item is dropped on this window.
+ * @return TRUE if the drop was valid, otherwise FALSE
+ */
+void CDropProxy::dropEvent(QDropEvent *event)
+{
+ if (m_Parent) {
+ long theCount = GetDragItemCount(event->mimeData());
+ for (long theIndex = 0; theIndex < theCount; ++theIndex) {
+ Qt::KeyboardModifiers theModifyerFlags = ReflectMouse(event->pos().x(), event->pos().y());
+
+ theModifyerFlags = CHotKeys::GetCurrentKeyModifiers();
+
+ CDropContainer::TFlavorItr theItr = m_Parent->GetFlavorBegin();
+ CDropContainer::TFlavorItr theEnd = m_Parent->GetFlavorEnd();
+
+ for (; theItr != theEnd; ++theItr) {
+ // Find the Flavor of this Item.
+ if (HasMainFlavor(event->mimeData(), *theItr)) {
+ // This will convert all stuff into a DropSource
+ CDropSource *theDropSource = GetDropSource(event->mimeData(), *theItr, theIndex);
+
+ // This will be implemented in the cross platform code.
+ if (theDropSource) {
+ CPt thePoint(event->pos());
+ theDropSource->SetCurrentPoint(thePoint);
+ theDropSource->SetCurrentFlags(theModifyerFlags);
+
+ // Don't call the recieve if we did not have a valid droptarget to begin
+ // with.
+ if (theDropSource->GetHasValidTarget()) {
+ theDropSource->InterpretKeyFlags(theModifyerFlags);
+ // This will be implemented in the cross platform code.
+ m_Parent->OnDragReceive(*theDropSource);
+ }
+ }
+
+ // Don't delete the drop source here, the creator will destroy it
+ // delete theDropSource;
+ }
+ }
+ }
+ }
+
+ event->accept();
+}
+//===============================================================================
+/**
+ * This function is used to report back to the container where the mouse is during a drag.
+ * The container can send this to children as MouseOvers so the children can do mouseover
+ *things.
+ * @param inX the X position
+ * @param inY the Y position.
+ * @return the Key modifyers.
+ */
+Qt::KeyboardModifiers CDropProxy::ReflectMouse(long inX, long inY)
+{
+ Qt::KeyboardModifiers theModifierFlags = Qt::NoModifier;
+
+ if (m_Parent) {
+ // Get the mouse stuff
+ CPt theMouseLoc(inX, inY);
+
+ // Determine which modifier keys are down so that we can pass them along
+
+ theModifierFlags = CHotKeys::GetCurrentKeyModifiers();
+
+ // Pass the gesture into the studio control
+ m_Parent->OnReflectMouse(theMouseLoc, theModifierFlags);
+ }
+ return theModifierFlags;
+}
+
+void CDropProxy::Register(QWidget *widget)
+{
+ widget->installEventFilter(this);
+ widget->setAcceptDrops(true);
+}
+
+bool CDropProxy::eventFilter(QObject *watched, QEvent *event)
+{
+ Q_UNUSED(watched);
+
+ switch (event->type()) {
+ case QEvent::DragEnter:
+ dragEnterEvent(static_cast<QDragEnterEvent *>(event));
+ return event->isAccepted();
+ case QEvent::DragLeave:
+ dragLeaveEvent(static_cast<QDragLeaveEvent *>(event));
+ return event->isAccepted();
+ case QEvent::DragMove:
+ dragMoveEvent(static_cast<QDragMoveEvent *>(event));
+ return event->isAccepted();
+ case QEvent::Drop:
+ dropEvent(static_cast<QDropEvent *>(event));
+ return event->isAccepted();
+ default:
+ return false;
+ }
+}
diff --git a/src/Authoring/Studio/_Win/DragNDrop/DropProxy.h b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.h
new file mode 100644
index 00000000..eadb9b83
--- /dev/null
+++ b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_DROP_PROXY
+#define INCLUDED_DROP_PROXY 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <QObject>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+class CDropContainer;
+class CStudioApp;
+class CDropSource;
+
+class QDragEnterEvent;
+class QDragLeaveEvent;
+class QDragMoveEvent;
+class QDropEvent;
+class QMimeData;
+
+class CDropProxy : public QObject
+{
+ Q_OBJECT
+public:
+ CDropProxy(CDropContainer *inParent);
+ virtual ~CDropProxy();
+
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragLeaveEvent(QDragLeaveEvent *event);
+ void dragMoveEvent(QDragMoveEvent *event);
+ void dropEvent(QDropEvent *event);
+
+ CDropSource *GetDropSource(const QMimeData *inDataObject, long inFlavor, long inItem);
+ long GetDragItemCount(const QMimeData *inDataObject);
+ bool HasMainFlavor(const QMimeData *inDataObject, long inFlavor);
+ Qt::KeyboardModifiers ReflectMouse(long inX, long inY);
+
+ void Register(QWidget* widget);
+
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
+protected:
+ CDropContainer *m_Parent;
+};
+
+#endif // INCLUDED_DROP_PROXY
diff --git a/src/Authoring/Studio/_Win/DragNDrop/WinDnd.cpp b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.cpp
new file mode 100644
index 00000000..d6216200
--- /dev/null
+++ b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2003 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "WinDnd.h"
+#include "DropSource.h"
+
+//===============================================================================
+/**
+ * Constructor
+ */
+CWinDragManager::CWinDragManager()
+{
+ memset(&m_DragItem, 0, sizeof(SDropItem));
+}
+
+//===============================================================================
+/**
+ * Dtor
+ */
+CWinDragManager::~CWinDragManager()
+{
+}
+
+//===============================================================================
+/**
+ * This will take any data flavor and wrap it up into out drag data.
+ */
+void CWinDragManager::AddData(long inFlavor, void *inData, unsigned long inSize)
+{
+ m_DragItem.m_Flavor = inFlavor;
+ m_DragItem.m_Data = inData;
+ m_DragItem.m_Size = inSize;
+}
+
+//===============================================================================
+/**
+ * I made this so it would kind of match the MAC version.
+ */
+void CWinDragManager::StartDrag()
+{
+ Track();
+}
+
+//===============================================================================
+/**
+ * This is the Blocking function that does the Dragging.
+ * It is assumed that all of the Data is is requested to be dragged, is already in the list
+ * and we take it out of the list and pack it into the Win OLEDropSource and let it go.
+ * We should only return when the whole operation is over.
+ */
+void CWinDragManager::Track()
+{
+ // Convert our data into a OLE DragSource.
+ HGLOBAL theGlobalData = nullptr;
+ COleDataSource theDataSource;
+
+ // Empty the data source
+ theDataSource.Empty();
+
+ // long theDataSize = m_DragItem.m_Size;
+ void *theData = m_DragItem.m_Data;
+ long theFlavor = m_DragItem.m_Flavor;
+
+ // if ( theDataSize > 0 )
+ {
+ // Allocate a global block of data
+ DWORD theGlobalObjectSize = sizeof(CDropSource *);//sizeof(long /*theDataSize*/);
+ theGlobalData = GlobalAlloc(GHND, theGlobalObjectSize);
+
+ // Lock down the global memory object for copying data
+ CDropSource *theDropSource = reinterpret_cast<CDropSource *>(GlobalLock(theGlobalData));
+
+ // Copy the CDropSource pointer
+ CopyMemory(theDropSource, theData, theGlobalObjectSize);
+
+ // Unlock, but do not free
+ GlobalUnlock(theGlobalData);
+
+ // Prepare OLE data for transfer
+ theDataSource.CacheGlobalData((CLIPFORMAT)theFlavor, theGlobalData, nullptr);
+ }
+
+ // This will go through the framework.
+ if (DROPEFFECT_NONE == theDataSource.DoDragDrop()) {
+ theDataSource.Empty();
+ if (theGlobalData)
+ ::GlobalFree(theGlobalData);
+ }
+}
diff --git a/src/Authoring/Studio/_Win/DragNDrop/WinDnd.h b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.h
new file mode 100644
index 00000000..8af759c7
--- /dev/null
+++ b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2003 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#ifndef INCLUDED_WINDND
+#define INCLUDED_WINDND
+
+#include <map>
+
+typedef struct _SDropItem
+{
+ long m_Flavor; // The Type of Data.
+ void *m_Data; ///< A nullptr value will cause the Data to be created Later on ( Promise )
+ unsigned long m_Size; //< The size of the Data.
+} SDropItem;
+
+//=============================================================================
+/**
+ * This class only supports dragging one item.
+ */
+class CWinDragManager
+{
+protected:
+ SDropItem m_DragItem; ///< the dragged item
+
+public:
+ CWinDragManager();
+ virtual ~CWinDragManager();
+
+ void Track();
+ void StartDrag();
+
+ void AddData(long inFlavor, void *inData, unsigned long inSize);
+};
+
+#endif
diff --git a/src/Authoring/Studio/_Win/Include/StudioPrefixWin32.h b/src/Authoring/Studio/_Win/Include/StudioPrefixWin32.h
new file mode 100644
index 00000000..114e3bf8
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Include/StudioPrefixWin32.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STUDIO_PREFIX_WIN_32_H
+#define INCLUDED_STUDIO_PREFIX_WIN_32_H 1
+
+#pragma once
+
+#define AK_LITTLE_ENDIAN
+//#define WIN32
+
+#include <float.h>
+
+#endif // INCLUDED_STUDIO_PREFIX_WIN_32_H
diff --git a/src/Authoring/Studio/_Win/Palettes/PaletteManager.cpp b/src/Authoring/Studio/_Win/Palettes/PaletteManager.cpp
new file mode 100644
index 00000000..41f0fe42
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/PaletteManager.cpp
@@ -0,0 +1,902 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PaletteManager.h"
+#include "StudioApp.h"
+#include "Views.h"
+#include "MainFrm.h"
+#include "StringLoader.h"
+#include "TimelineControl.h"
+#include "BasicObjectsView.h"
+#include "SlideView.h"
+#include "StringTokenizer.h"
+#include "Preferences.h"
+#include "WidgetControl.h"
+#include "InspectorControlView.h"
+#include "ActionView.h"
+#include "IDragable.h"
+#include "ActionView.h"
+#include "ProjectView.h"
+#include "TabOrderHandler.h"
+
+#include <QDockWidget>
+
+//==============================================================================
+/**
+ * Class for std::for_each to delete each control
+ */
+template <class T>
+class CDeleteAll
+{
+public:
+ void operator()(const T *inControl) const { delete inControl; }
+};
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CPaletteManager::CPaletteManager(CMainFrame *inMainFrame)
+ : m_MainFrame(inMainFrame)
+{
+ // Position tabs to the right
+ inMainFrame->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::East);
+
+ QDockWidget *basicObjectsDock = new QDockWidget(QObject::tr("Basic Objects"), inMainFrame);
+ basicObjectsDock->setObjectName("basic_objects");
+ basicObjectsDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea
+ | Qt::BottomDockWidgetArea);
+ auto basicObjectsView = new BasicObjectsView(basicObjectsDock);
+ basicObjectsDock->setWidget(basicObjectsView);
+ inMainFrame->addDockWidget(Qt::RightDockWidgetArea, basicObjectsDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_BASICOBJECTS, basicObjectsDock));
+
+ QDockWidget *projectDock = new QDockWidget(QObject::tr("Project"), inMainFrame);
+ projectDock->setObjectName("project");
+ projectDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea
+ | Qt::BottomDockWidgetArea);
+ auto projectView = new ProjectView(projectDock);
+ projectDock->setWidget(projectView);
+ inMainFrame->addDockWidget(Qt::RightDockWidgetArea, projectDock);
+ inMainFrame->tabifyDockWidget(basicObjectsDock, projectDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_PROJECT, projectDock));
+
+ QDockWidget *slideDock = new QDockWidget(QObject::tr("Slide"), inMainFrame);
+ slideDock->setObjectName("slide");
+ slideDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+ auto slideView = new SlideView(slideDock);
+ slideDock->setWidget(slideView);
+ inMainFrame->addDockWidget(Qt::LeftDockWidgetArea, slideDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_SLIDE, slideDock));
+
+ QDockWidget *timelineDock = new QDockWidget(QObject::tr("Timeline"), inMainFrame);
+ timelineDock->setObjectName("timeline");
+ timelineDock->setAllowedAreas(Qt::BottomDockWidgetArea);
+ auto c = new CTimelineControl();
+ auto w = new WidgetControl(c, timelineDock);
+ timelineDock->setWidget(w);
+ w->setMinimumWidth(500);
+ inMainFrame->addDockWidget(Qt::BottomDockWidgetArea, timelineDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_TIMELINE, timelineDock));
+
+ int actionViewMinWidth = CStudioPreferences::valueWidth()
+ + CStudioPreferences::idWidth() + 40; // 40 added to accommodate tabs
+
+ QDockWidget *actionDock = new QDockWidget(QObject::tr("Action"), inMainFrame);
+ actionDock->setObjectName("action");
+ actionDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea
+ | Qt::BottomDockWidgetArea);
+ auto actionView = new ActionView(actionDock);
+ actionDock->setWidget(actionView);
+ actionView->setMinimumWidth(actionViewMinWidth);
+ inMainFrame->addDockWidget(Qt::BottomDockWidgetArea, actionDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_ACTION, actionDock));
+
+ QDockWidget *inspectorDock = new QDockWidget(QObject::tr("Inspector Control"), inMainFrame);
+ inspectorDock->setObjectName("inspector_control");
+ inspectorDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea
+ | Qt::BottomDockWidgetArea);
+ auto inspectorView = new InspectorControlView(inspectorDock);
+ inspectorDock->setWidget(inspectorView);
+ inspectorView->setMinimumWidth(actionViewMinWidth); // Same min size as action view
+ inMainFrame->addDockWidget(Qt::BottomDockWidgetArea, inspectorDock);
+ inMainFrame->tabifyDockWidget(actionDock, inspectorDock);
+ m_ControlList.insert(std::make_pair(CONTROLTYPE_INSPECTOR, inspectorDock));
+
+ w->RegiserForDnd(w);
+ w->AddMainFlavor(EUIC_FLAVOR_LISTBOX);
+ w->AddMainFlavor(EUIC_FLAVOR_FILE);
+ w->AddMainFlavor(EUIC_FLAVOR_ASSET_UICFILE);
+ w->AddMainFlavor(EUIC_FLAVOR_ASSET_LIB);
+ w->AddMainFlavor(EUIC_FLAVOR_ASSET_TL);
+ w->AddMainFlavor(EUIC_FLAVOR_BASIC_OBJECTS);
+
+ // Set to a default state
+ Reset();
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CPaletteManager::~CPaletteManager()
+{
+ TControlMap::iterator theIterator = m_ControlList.begin();
+ TControlMap::iterator theEndIterator = m_ControlList.end();
+#ifdef KDAB_TEMPORARILY_REMOVED
+ for (; theIterator != theEndIterator; ++theIterator) {
+ // Remove the palette from the old master
+ long theType = theIterator->first;
+ CMasterControl *theOldMaster = FindMasterPalette(theType);
+ if (theOldMaster)
+ RemoveControlFromMaster(theOldMaster, theType);
+ }
+ std::for_each(m_PaletteList.begin(), m_PaletteList.end(), CDeleteAll<CStudioPaletteBar>());
+#endif
+ // Delete all the controls
+ for (theIterator = m_ControlList.begin(); theIterator != theEndIterator; ++theIterator)
+ delete theIterator->second;
+}
+
+//==============================================================================
+/**
+ * Clear out old lists and reset all the palettes
+ */
+void CPaletteManager::Reset()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Set the visible state to false
+ TControlMap::iterator theIterator = m_ControlList.begin();
+ TControlMap::iterator theEndIterator = m_ControlList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ CControl *theControl = theIterator->second;
+ if (theControl)
+ theControl->SetVisible(false);
+ }
+
+ // Undock all palette
+ TPaletteList::iterator thePaletteIterator = m_PaletteList.begin();
+ for (; thePaletteIterator != m_PaletteList.end(); ++thePaletteIterator) {
+ CStudioPaletteBar *thePaletteBar = (*thePaletteIterator);
+ thePaletteBar->ShowPalette(false);
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Create a palette
+ */
+CStudioPaletteBar *CPaletteManager::CreatePalette()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Build the create context
+ CCreateContext theCreateContext;
+ memset(&theCreateContext, 0, sizeof(CCreateContext));
+ theCreateContext.m_pNewViewClass = RUNTIME_CLASS(CMasterView);
+ theCreateContext.m_pCurrentFrame = m_MainFrame;
+
+ // Create the palette bar
+ CStudioPaletteBar *thePaletteBar = new CStudioPaletteBar;
+ thePaletteBar->Create(::CString("<empty>"), &theCreateContext, GetUniquePaletteId(),
+ m_MainFrame);
+
+ // Set the provider
+ CMasterView *theMasterView = (CMasterView *)thePaletteBar->GetView();
+ theMasterView->SetProvider(this);
+
+ // Must occur after the provider is set
+ thePaletteBar->InitialUpdate();
+
+ // Save the palette
+ ASSERT(thePaletteBar != nullptr);
+ m_PaletteList.push_back(thePaletteBar);
+
+ // Store the information
+ TSMasterInfo theInfo;
+ theInfo.m_Master = theMasterView->GetMasterControl();
+ theInfo.m_PaletteBar = thePaletteBar;
+
+ ASSERT(theInfo.m_PaletteBar != nullptr);
+ m_MasterList.push_back(theInfo);
+
+ return thePaletteBar;
+#endif
+ return nullptr;
+}
+
+//==============================================================================
+/**
+ * Find a master control with no contained controls
+ */
+CMasterControl *CPaletteManager::FindUnusedMaster()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ if (theIterator->m_Palettes.any() == false)
+ return theIterator->m_Master;
+ }
+#endif
+
+ return nullptr;
+}
+
+CMasterControl *CPaletteManager::FindMasterByPaletteId(long inPaletteId)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ CControlBarInfo theBarInfo;
+ theIterator->m_PaletteBar->GetBarInfo(&theBarInfo);
+
+ if (theBarInfo.m_nBarID == (UINT)inPaletteId)
+ return theIterator->m_Master;
+ }
+#endif
+ return nullptr;
+}
+
+CStudioPaletteBar *CPaletteManager::FindStudioPaletteBar(long inType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ if (theIterator->m_Palettes[inType] == true)
+ return theIterator->m_PaletteBar;
+ }
+#endif
+ return nullptr;
+}
+
+CStudioPaletteBar *CPaletteManager::FindStudioPaletteBar(CMasterControl *inMaster)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ if (theIterator->m_Master == inMaster)
+ return theIterator->m_PaletteBar;
+ }
+#endif
+ return nullptr;
+}
+
+//==============================================================================
+/**
+ * Add a new master to the list of masters
+ */
+CMasterControl *CPaletteManager::AddMasterPalette(long inType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Remove the palette from the old master
+ CMasterControl *theOldMaster = FindMasterPalette(inType);
+ if (theOldMaster)
+ RemoveControlFromMaster(theOldMaster, inType);
+
+ // Create a new master
+ CMasterControl *theMasterControl = FindUnusedMaster();
+ if (theMasterControl != nullptr) {
+ // Add the palette to the new master
+ AddControlToMaster(theMasterControl, inType);
+ }
+
+ return theMasterControl;
+#endif
+ return nullptr;
+}
+
+//==============================================================================
+/**
+ * Add the specified palette to the specified master
+ */
+void CPaletteManager::AddControlToMaster(CMasterControl *inMaster, long inType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Make sure this is a valid type ( for backward compatibility )
+ TControlMap::iterator theControlIterator = m_ControlList.find(inType);
+ if (theControlIterator != m_ControlList.end()) {
+ // Make sure the palette is not already on another master
+ CMasterControl *theOldMaster = FindMasterPalette(inType);
+ if (theOldMaster)
+ RemoveControlFromMaster(theOldMaster, inType);
+
+ // Add the palette to this master
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ for (; theIterator != m_MasterList.end(); ++theIterator) {
+ if (theIterator->m_Master == inMaster) {
+ theIterator->m_Palettes[inType] = true;
+ theIterator->m_Master->AddControl(GetControlName(inType), inType,
+ theControlIterator->second);
+ theIterator->m_Master->Invalidate();
+ break;
+ }
+ }
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Remove the specified palette from the specified master
+ */
+void CPaletteManager::RemoveControlFromMaster(CMasterControl *inMaster, long inType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ for (; theIterator != m_MasterList.end(); ++theIterator) {
+ if (theIterator->m_Master == inMaster) {
+ theIterator->m_Palettes[inType] = false;
+ theIterator->m_Master->RemoveControl(GetControl(inType));
+ theIterator->m_Master->Invalidate();
+ }
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Find the name of the master that contains this palette
+ */
+CMasterControl *CPaletteManager::FindMasterPalette(long inType)
+{
+ CMasterControl *theMaster = nullptr;
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (; theIterator != theEndIterator; ++theIterator) {
+ if (theIterator->m_Palettes[inType] == true) {
+ theMaster = theIterator->m_Master;
+ break;
+ }
+ }
+#endif
+ return theMaster;
+}
+
+//==============================================================================
+/**
+ * Query the number of masters
+ */
+long CPaletteManager::GetMasterCount()
+{
+ return (long)m_MasterList.size();
+}
+
+//==============================================================================
+/**
+ * Get the master at the specified index
+ */
+CMasterControl *CPaletteManager::GetMaster(long inIndex)
+{
+ CMasterControl *theControl = nullptr;
+#ifdef KDAB_TEMPORARILY_REMOVED
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ std::advance(theIterator, inIndex);
+ if (theIterator != m_MasterList.end())
+ theControl = theIterator->m_Master;
+#endif
+ return theControl;
+}
+
+//=============================================================================
+/**
+ * Force a control to become invisible
+ */
+void CPaletteManager::HideControl(long inType)
+{
+ auto dock = GetControl(inType);
+
+ if (dock) {
+ // Make sure the control is invisible
+ dock->setVisible(false);
+ }
+}
+//=============================================================================
+/**
+ * Detemine if a control is currently visible
+ */
+bool CPaletteManager::IsControlVisible(long inType) const
+{
+ auto dock = GetControl(inType);
+ return dock && dock->isVisible();
+}
+
+//=============================================================================
+/**
+ * Force a control to become visible
+ */
+void CPaletteManager::ShowControl(long inType)
+{
+ auto dock = GetControl(inType);
+
+ if (dock) {
+ // Make sure the control is visible
+ dock->setVisible(true);
+ dock->setFocus();
+ }
+}
+
+//=============================================================================
+/**
+ * Flip the visible state of a control
+ */
+void CPaletteManager::ToggleControl(long inType)
+{
+ if (IsControlVisible(inType))
+ HideControl(inType);
+ else
+ ShowControl(inType);
+}
+
+//==============================================================================
+/**
+ * Return the Control (Palette) according to its EControlTypes enum.
+ * @param inType EControlTypes
+ */
+QDockWidget *CPaletteManager::GetControl(long inType) const
+{
+ auto dock = m_ControlList.find(inType);
+ if (dock != m_ControlList.end() && dock->second)
+ return dock->second;
+ else
+ return nullptr;
+}
+
+QWidget *CPaletteManager::getFocusWidget() const
+{
+ TControlMap::const_iterator end = m_ControlList.end();
+ for (TControlMap::const_iterator iter = m_ControlList.begin(); iter != end; ++iter) {
+ if (iter->second->widget()->hasFocus())
+ return iter->second->widget();
+ }
+ return nullptr;
+}
+
+bool CPaletteManager::tabNavigateFocusedWidget(bool tabForward)
+{
+ QWidget *palette = getFocusWidget();
+ if (palette) {
+ if (auto inspector = qobject_cast<InspectorControlView *>(palette)) {
+ inspector->tabOrderHandler()->tabNavigate(tabForward);
+ return true;
+ } else if (auto actionview = qobject_cast<ActionView *>(palette)) {
+ actionview->tabOrderHandler()->tabNavigate(tabForward);
+ return true;
+ }
+ }
+ return false;
+}
+
+//==============================================================================
+/**
+ * A helper for CMainFrame::GetTimelineControl() to access the CTimelineControl
+ * inside the QDockWidget
+ */
+CTimelineControl *CPaletteManager::GetTimelineControl() const
+{
+ auto dock = GetControl(CPaletteManager::CONTROLTYPE_TIMELINE);
+
+ if (dock) {
+ auto widget = static_cast<WidgetControl *>(dock->widget());
+
+ if (widget)
+ return static_cast<CTimelineControl *>(widget->getControl());
+ }
+
+ return nullptr;
+}
+
+//==============================================================================
+// Serialization
+//==============================================================================
+
+//==============================================================================
+/**
+ * Load the palette state from the registry
+ */
+bool CPaletteManager::Load()
+{
+ // Clear out existing local stuff
+ Reset();
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Test the palette prefs, return false if they don't exist
+ if (CPreferences::GetUserPreferences().Exists(PALETTE_KEY) == false)
+ return false;
+
+ long theCurrentPalette = 0;
+ while (true) {
+ // Format the subkey name
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%ls%ld", PALETTE_SUBKEY, theCurrentPalette);
+
+ // Check to see if we should exit the for loop
+ CPreferences thePalettePrefs = CPreferences::GetUserPreferences(PALETTE_KEY);
+ if (thePalettePrefs.Exists(theSubKeyName) == false)
+ break;
+
+ // Format the subkey name
+ Q3DStudio::CString theFullKeyName;
+ theFullKeyName.Format(L"%ls\\%ls%ld", PALETTE_KEY, PALETTE_SUBKEY, theCurrentPalette);
+
+ // Grab the prefs
+ CPreferences thePrefs = CPreferences::GetUserPreferences(theFullKeyName);
+
+ // Default docking value
+ Q3DStudio::CString theDockString =
+ thePrefs.GetStringValue(PALETTE_CONTROL_DOCKID, L"0"); // left
+ long theDockId = ::atol(theDockString.GetCharStar());
+
+ // Default Rect
+ QRect theWindowRect;
+ Q3DStudio::CString theRectString =
+ thePrefs.GetStringValue(PALETTE_CONTROL_RECT, L"0,0,0,0");
+ CStringTokenizer theRectTokenizer(theRectString, L",");
+ for (long theIndex = 0; theRectTokenizer.HasNextPartition();
+ ++theRectTokenizer, ++theIndex) {
+ Q3DStudio::CString theCurrentString = theRectTokenizer.GetCurrentPartition();
+ long theCurrentItem = ::atol(theCurrentString.GetCharStar());
+
+ switch (theIndex) {
+ case 0:
+ theWindowRect.setLeft(theCurrentItem);
+ break;
+ case 1:
+ theWindowRect.setTop(theCurrentItem);
+ break;
+ case 2:
+ theWindowRect.setRight(theCurrentItem);
+ break;
+ case 3:
+ theWindowRect.setBottom(theCurrentItem);
+ break;
+ };
+ }
+
+ // Palette id
+ Q3DStudio::CString thePaletteIdString =
+ thePrefs.GetStringValue(PALETTE_CONTROL_PALETTEID, L"0");
+ long thePaletteId = ::atol(thePaletteIdString.GetCharStar());
+
+ // Read the selected item
+ Q3DStudio::CString theSelectedString =
+ thePrefs.GetStringValue(PALETTE_CONTROL_SELECTED, L"0");
+ long theSelectedType = ::atol(theSelectedString.GetCharStar());
+
+ // Grab the palette
+ CMasterControl *theMasterControl;
+ if (thePaletteId)
+ theMasterControl = FindMasterByPaletteId(thePaletteId);
+ else
+ theMasterControl = FindUnusedMaster();
+
+ if (theMasterControl != nullptr) {
+ CStudioPaletteBar *thePaletteBar = FindStudioPaletteBar(theMasterControl);
+
+ Q3DStudio::CString theContentString =
+ thePrefs.GetStringValue(PALETTE_CONTROL_LIST, L"0");
+ CStringTokenizer theTokenizer(theContentString, L",");
+ for (; theTokenizer.HasNextPartition(); ++theTokenizer) {
+ Q3DStudio::CString theCurrentString = theTokenizer.GetCurrentPartition();
+ long theCurrentItem = ::atol(theCurrentString.GetCharStar());
+
+ if (theCurrentItem != CONTROLTYPE_NONE)
+ AddControlToMaster(theMasterControl, theCurrentItem);
+ }
+
+ // Dock the bar in the appropriate location (if requested)
+ if (theDockId != 0) {
+ CDockBar *theDockBar =
+ (CDockBar *)m_MainFrame->GetControlBar(theDockId + AFX_IDW_DOCKBAR_TOP);
+ theDockBar->ClientToScreen(theWindowRect);
+
+ thePaletteBar->SetHorz(CSize(theWindowRect.Width(), theWindowRect.Height()));
+ thePaletteBar->SetVert(CSize(theWindowRect.Width(), theWindowRect.Height()));
+
+ m_MainFrame->DockControlBar(thePaletteBar, theDockBar, theWindowRect);
+ m_MainFrame->RecalcLayout(TRUE);
+ }
+
+ // Select the old item
+ theMasterControl->SelectControl(theSelectedType);
+
+ // Turn on my heart light
+ thePaletteBar->ShowPalette(true);
+ }
+
+ // Move on to the next key
+ theCurrentPalette++;
+ }
+
+ if (m_MainFrame) {
+ // Allow the control bars (docking palettes, etc) the opportunity to restore
+ // This will use a registry key based off of AFX_IDS_APP_TITLE ("Qt 3D Studio") which
+ // is different than CPreferences (".../Qt 3D Studio/Settings/...")
+ CSizingControlBar::GlobalLoadState(m_MainFrame, PALETTE_LAYOUT_KEY_NAME);
+ m_MainFrame->LoadBarState(PALETTE_LAYOUT_KEY_NAME);
+ }
+#endif
+
+ return true;
+}
+
+//==============================================================================
+/**
+ * Save the palette state to the registry
+ */
+void CPaletteManager::Save()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Destroy current information in the prefs
+ CPreferences theMasterPrefs = CPreferences::GetUserPreferences(PALETTE_KEY);
+ theMasterPrefs.Clear();
+
+ // Iterate through the m_MasterList
+ TMasterList::iterator theIterator = m_MasterList.begin();
+ TMasterList::iterator theEndIterator = m_MasterList.end();
+ for (long theMasterIndex = 0; theIterator != theEndIterator; ++theIterator) {
+ TSMasterInfo &theMasterInfo = *theIterator;
+ if (theMasterInfo.m_PaletteBar->IsVisible()) {
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%ls\\%ls%ld", PALETTE_KEY, PALETTE_SUBKEY, theMasterIndex);
+
+ CPreferences thePrefs = CPreferences::GetUserPreferences(theSubKeyName);
+
+ // Save palette contents
+ Q3DStudio::CString theTempString;
+ Q3DStudio::CString theContentString;
+ for (long theIndex = 0; theIndex < (long)theMasterInfo.m_Palettes.size(); ++theIndex) {
+ if (theMasterInfo.m_Palettes[theIndex]) {
+ theTempString.Format(L"%ld,", theIndex);
+ theContentString += theTempString;
+ }
+ }
+
+ thePrefs.SetStringValue(PALETTE_CONTROL_LIST, theContentString);
+
+ // Save palette id
+ CControlBarInfo theBarInfo;
+ theMasterInfo.m_PaletteBar->GetBarInfo(&theBarInfo);
+ theTempString.Format(L"%ld", theBarInfo.m_nBarID);
+ thePrefs.SetStringValue(PALETTE_CONTROL_PALETTEID, theTempString);
+
+ // Save selected item
+ long theSelectedIndex = theMasterInfo.m_Master->GetActiveIndex();
+ theTempString.Format(L"%ld", theSelectedIndex);
+ thePrefs.SetStringValue(PALETTE_CONTROL_SELECTED, theTempString);
+
+ // Default values
+ thePrefs.SetStringValue(PALETTE_CONTROL_DOCKID, L"0");
+ thePrefs.SetStringValue(PALETTE_CONTROL_RECT, L"0,0,0,0");
+
+ // Increment the palette counter
+ ++theMasterIndex;
+ }
+ }
+
+ // Allow the control bars (docking palettes, etc) the opportunity to store
+ // This will use a registry key based off of AFX_IDS_APP_TITLE ("Qt 3D Studio") which
+ // is different than CPreferences (".../Qt 3D Studio/Settings/...")
+ if (m_MainFrame) {
+ CSizingControlBar::GlobalSaveState(m_MainFrame, PALETTE_LAYOUT_KEY_NAME);
+ m_MainFrame->SaveBarState(PALETTE_LAYOUT_KEY_NAME);
+ }
+#endif
+}
+
+//==============================================================================
+// Defaults
+//==============================================================================
+
+//==============================================================================
+/**
+ * Set the palettes to the default state
+ *
+ * CONTROLTYPE_ACTION = 1, ///<
+ * CONTROLTYPE_BASICOBJECTS = 3, ///<
+ * CONTROLTYPE_INSPECTOR = 4, ///<
+ * CONTROLTYPE_SLIDE = 6, ///<
+ * CONTROLTYPE_TIMELINE = 7, ///<
+ * CONTROLTYPE_COMMAND = 8, ///<
+ * CONTROLTYPE_PROJECT = 9, ///<
+ *
+ * #define AFX_IDW_DOCKBAR_TOP 0xE81B = 0
+ * #define AFX_IDW_DOCKBAR_LEFT 0xE81C = 1
+ * #define AFX_IDW_DOCKBAR_RIGHT 0xE81D = 2
+ * #define AFX_IDW_DOCKBAR_BOTTOM 0xE81E = 3
+ * #define AFX_IDW_DOCKBAR_FLOAT 0xE81F = 4
+ */
+void CPaletteManager::RestoreDefaults(bool inForce)
+{
+ Q_UNUSED(inForce);
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+ // Destroy current information in the prefs (Palettes)
+ CPreferences theMasterPrefs = CPreferences::GetUserPreferences(PALETTE_KEY);
+ theMasterPrefs.Clear();
+
+ // "3,9,2,5:0:2:0,0,300,250#4,1:0:2:0,251,300,601#6:0:1:0,0,125,125#7:0:3:0,0,250,300";
+ Q3DStudio::CString thePaletteString = ::LoadResourceString(IDS_DEFAULT_PALETTE_LAYOUT);
+ CStringTokenizer thePaletteTokenizer(thePaletteString, L"#");
+ for (long thePaletteIndex = 0; thePaletteTokenizer.HasNextPartition();
+ ++thePaletteTokenizer, ++thePaletteIndex) {
+ Q3DStudio::CString theCurrentPalette = thePaletteTokenizer.GetCurrentPartition();
+ CStringTokenizer theSubTokenizer(theCurrentPalette, L":");
+
+ // No error checking, this string better be right!
+ Q3DStudio::CString theControlList = theSubTokenizer.GetCurrentPartition();
+ ++theSubTokenizer;
+ Q3DStudio::CString theSelectedControl = theSubTokenizer.GetCurrentPartition();
+ ++theSubTokenizer;
+ Q3DStudio::CString theDockId = theSubTokenizer.GetCurrentPartition();
+ ++theSubTokenizer;
+ Q3DStudio::CString theControlRect = theSubTokenizer.GetCurrentPartition();
+ ++theSubTokenizer;
+
+ // Create the new registry keys (Palettes\PaletteN)
+ Q3DStudio::CString theSubKeyName;
+ theSubKeyName.Format(L"%ls\\%s%ld", PALETTE_KEY, PALETTE_SUBKEY, thePaletteIndex);
+ CPreferences thePrefs = CPreferences::GetUserPreferences(theSubKeyName);
+
+ thePrefs.SetStringValue(PALETTE_CONTROL_LIST, theControlList);
+ thePrefs.SetStringValue(PALETTE_CONTROL_SELECTED, theSelectedControl);
+ thePrefs.SetStringValue(PALETTE_CONTROL_DOCKID, theDockId);
+ thePrefs.SetStringValue(PALETTE_CONTROL_RECT, theControlRect);
+ }
+#endif
+ // Load these items
+ Load();
+}
+
+//==============================================================================
+// Palette Context Menu
+//==============================================================================
+
+//=============================================================================
+/**
+ * Callback to create a new palette of the specified type.
+ */
+void CPaletteManager::OnNewPalette(CMasterControl *inMaster)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ ASSERT(inMaster != nullptr);
+
+ // Query the current control type
+ long theType = inMaster->GetActiveType();
+
+ // Add a new master with that control type
+ CMasterControl *theNewMaster = AddMasterPalette(theType);
+
+ // Float the new palette
+ CStudioPaletteBar *thePaletteBar = FindStudioPaletteBar(theNewMaster);
+ m_MainFrame->FloatControlBar(thePaletteBar, QPoint(0, 0));
+
+ // Turn on my heart light
+ thePaletteBar->ShowPalette(true);
+#endif
+}
+
+//=============================================================================
+/**
+ * Callback to move a control to the specified palette
+ */
+void CPaletteManager::OnMovePalette(CMasterControl *inMoveFromMaster,
+ CMasterControl *inMoveToMaster)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ ASSERT(inMoveFromMaster != nullptr);
+ ASSERT(inMoveToMaster != nullptr);
+
+ // Move the control to the new master
+ long theType = inMoveFromMaster->GetActiveType();
+ AddControlToMaster(inMoveToMaster, theType);
+
+ // Check to see if the master is empty
+ if (inMoveFromMaster->GetControlCount() <= 0) {
+ // Make sure the palette is visible
+ CStudioPaletteBar *thePaletteBar = FindStudioPaletteBar(inMoveFromMaster);
+ thePaletteBar->ShowPalette(false);
+ }
+#endif
+}
+
+//==============================================================================
+// IMasterControlProvider
+//==============================================================================
+
+void CPaletteManager::OnControlRemoved(CMasterControl *inMaster)
+{
+ (void)inMaster;
+}
+
+void CPaletteManager::OnContextMenu(CMasterControl *inMaster, const CPt &inPosition,
+ CContextMenu *inMyMenu)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CPaletteContextMenu theContextMenu(this, inMaster, inMyMenu);
+
+ // Popup the context menu
+ inMaster->DoPopup(&theContextMenu, inPosition);
+#endif
+}
+
+void CPaletteManager::OnControlSelected(CMasterControl *inMaster, CControl *, long inType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ Q3DStudio::CString theControlName = GetControlName(inType);
+
+ CStudioPaletteBar *thePalette = FindStudioPaletteBar(inMaster);
+ ASSERT(thePalette != nullptr);
+
+ thePalette->SetWindowText(theControlName);
+#endif
+}
+
+//==============================================================================
+// Static Methods
+//==============================================================================
+
+//==============================================================================
+/**
+ * Query the name of the specified palette
+ */
+Q3DStudio::CString CPaletteManager::GetControlName(long inType)
+{
+ switch (inType) {
+ case CONTROLTYPE_ACTION:
+ return ::LoadResourceString(IDS_PALETTE_ACTION);
+ case CONTROLTYPE_BASICOBJECTS:
+ return ::LoadResourceString(IDS_PALETTE_BASIC_OBJECTS);
+ case CONTROLTYPE_INSPECTOR:
+ return ::LoadResourceString(IDS_PALETTE_INSPECTOR);
+ case CONTROLTYPE_SLIDE:
+ return ::LoadResourceString(IDS_PALETTE_SLIDE);
+ case CONTROLTYPE_TIMELINE:
+ return ::LoadResourceString(IDS_PALETTE_TIMELINE);
+ case CONTROLTYPE_PROJECT:
+ return ::LoadResourceString(IDS_PALETTE_PROJECT);
+ default:
+ return L"< Empty >";
+ };
+}
+
diff --git a/src/Authoring/Studio/_Win/Palettes/PaletteManager.h b/src/Authoring/Studio/_Win/Palettes/PaletteManager.h
new file mode 100644
index 00000000..e162e7f7
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/PaletteManager.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_VIEW_MANAGER_H
+#define INCLUDED_VIEW_MANAGER_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <bitset>
+#include "MasterControl.h"
+#include "TimelineControl.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CStudioApp;
+class CMainFrame;
+class CStudioPaletteBar;
+
+class QDockWidget;
+
+//==============================================================================
+/**
+ * @class CPaletteManager
+ */
+class CPaletteManager : public IMasterControlProvider
+{
+public:
+ // Do NOT change the order/values of this enum, these
+ // values are stored in the registry
+ enum EControlTypes {
+ CONTROLTYPE_NONE = 0, ///<
+ CONTROLTYPE_ACTION = 1, ///<
+ CONTROLTYPE_BASICOBJECTS = 3, ///<
+ CONTROLTYPE_INSPECTOR = 4, ///<
+ CONTROLTYPE_SLIDE = 6, ///<
+ CONTROLTYPE_TIMELINE = 7, ///<
+ CONTROLTYPE_PROJECT = 9, ///<
+
+ CONTROLTYPE_MAXCONTROLS = 32, ///< the maximum number of palettes( a string of this length
+ ///is saved in the registry, changing this value will require
+ ///an upgrade process )
+ };
+
+public:
+ typedef std::bitset<CONTROLTYPE_MAXCONTROLS> TPaletteSet;
+
+protected:
+ typedef struct _TSMasterInfo
+ {
+ CStudioPaletteBar *m_PaletteBar; ///< pointer to the master palette bar
+ TPaletteSet m_Palettes; ///< the palettes contained by the master
+ CMasterControl *m_Master; ///< pointer to the master control
+
+ } TSMasterInfo;
+
+ typedef std::map<long, QDockWidget *> TControlMap;
+ typedef std::vector<CStudioPaletteBar *> TPaletteList;
+ typedef std::vector<TSMasterInfo> TMasterList;
+
+protected:
+ CMainFrame *m_MainFrame; ///<
+ TControlMap m_ControlList; ///< map of EControlTypes and CControl
+ TPaletteList m_PaletteList; ///<
+ TMasterList m_MasterList; ///<
+
+ static long s_PaletteIDBase; ///<
+
+public:
+ CPaletteManager(CMainFrame *inMainFrame);
+ virtual ~CPaletteManager();
+
+ // Access
+ void AddControlToMaster(CMasterControl *inControl, long inType);
+ void RemoveControlFromMaster(CMasterControl *inControl, long inType);
+ CMasterControl *FindMasterPalette(long inType);
+ long GetMasterCount();
+ CMasterControl *GetMaster(long inIndex);
+ void HideControl(long inType);
+ bool IsControlVisible(long inType) const;
+ void ShowControl(long inType);
+ void ToggleControl(long inType);
+
+ QDockWidget *GetControl(long inType) const; ///< return corresponding Palette according to EControlTypes enum value
+ QWidget *getFocusWidget() const;
+ bool tabNavigateFocusedWidget(bool tabForward);
+ CTimelineControl *GetTimelineControl() const;
+
+ // Commands
+ void OnNewPalette(CMasterControl *inMaster);
+ void OnMovePalette(CMasterControl *inMoveFromMaster, CMasterControl *inMoveToMaster);
+
+ // Serialization
+ bool Load();
+ void Save();
+
+ // Defaults
+ void RestoreDefaults(bool inForce = false);
+
+ // IMasterControlProvider
+ void OnControlRemoved(CMasterControl *inControl) override;
+ void OnContextMenu(CMasterControl *inControl, const CPt &inPosition,
+ CContextMenu *inMyMenu) override;
+ void OnControlSelected(CMasterControl *inMaster, CControl *inNewControl, long inType) override;
+
+ // Static Methods
+ static Q3DStudio::CString GetControlName(long inType);
+
+protected:
+ CMasterControl *AddMasterPalette(long inType);
+
+ void Reset();
+ CStudioPaletteBar *CreatePalette();
+
+ CMasterControl *FindUnusedMaster();
+ CMasterControl *FindMasterByPaletteId(long inPaletteId);
+
+ CStudioPaletteBar *FindStudioPaletteBar(long inType);
+ CStudioPaletteBar *FindStudioPaletteBar(CMasterControl *inMaster);
+ void OnAsyncDestroyWindow(CStudioPaletteBar *inWnd);
+};
+
+#endif // INCLUDED_VIEW_MANAGER_H
diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.cpp b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.cpp
new file mode 100644
index 00000000..a9f1e546
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ProgressPalette.h"
+#include "StudioConst.h"
+#include "ResourceCache.h"
+#include "ResImage.h"
+#include "ProgressView.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CProgressPalette::CProgressPalette()
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CProgressPalette::~CProgressPalette()
+{
+}
+
+//==============================================================================
+/**
+ * A wrapper around the CMiniFrameWnd::Create() method.
+ * Simplifies the create parameters for the palette bar. Overridden because
+ * the loading screen is different from all the other palettes.
+ * @return The result from the Create() call (FALSE if unsuccessful)
+ */
+BOOL CProgressPalette::Create(CString inTitle, CCreateContext *inCreateContext,
+ CWnd *inParent /* = nullptr */)
+{
+ CString theWndClass = AfxRegisterWndClass(CS_DBLCLKS, ::LoadCursor(nullptr, IDC_WAIT));
+ BOOL theReturnValue = FALSE;
+
+ // Add the title of the bar to the registry location.
+ m_DialogName = inTitle;
+
+ // Get the rectangle that we want this splash screen to occupy in the middle of the screen
+ CPt theScreenSize = ::GetAvailableDisplaySize();
+ CResImage *theImage = CResourceCache::GetInstance()->GetBitmap("progress-screen.png");
+ CPt theImageSize = theImage->GetSize();
+ long theTitleBarHeight = ::GetSystemMetrics(SM_CYCAPTION);
+ long theXPos = theScreenSize.x / 2 - theImageSize.x / 2;
+ long theYPos = theScreenSize.y / 2 - theImageSize.y / 2;
+ CRect theWindowRect(theXPos, theYPos, theXPos + theImageSize.x,
+ theYPos + theImageSize.y + theTitleBarHeight);
+
+ // Create the dialog.
+ theReturnValue = CFrameWnd::Create(theWndClass, inTitle, WS_POPUP | WS_CAPTION, theWindowRect,
+ inParent, nullptr, 0, inCreateContext);
+
+ return theReturnValue;
+}
+
+//==============================================================================
+/**
+ * Sends a message to the view that the progress bar needs to be updated to a
+ * new percentage.
+ * @param inPercent New percent complete to be displayed
+ */
+void CProgressPalette::SetProgress(long inPercent)
+{
+ SendMessageToDescendants(WM_STUDIO_LOADPROGRESS, CProgressView::PROGRESSUPDATE_PERCENT,
+ static_cast<LPARAM>(inPercent));
+ Invalidate();
+ UpdateWindow();
+}
+
+//==============================================================================
+/**
+ * Sends a message to the view that the action text (saving/loading) needs to be changed.
+ * @param inFileName New file name to be displayed
+ */
+void CProgressPalette::SetActionText(const Q3DStudio::CString &inText)
+{
+ SendMessageToDescendants(WM_STUDIO_LOADPROGRESS, CProgressView::PROGRESSUPDATE_ACTIONTEXT,
+ reinterpret_cast<LPARAM>(&inText));
+}
+
+//==============================================================================
+/**
+ * Sends a message to the view that the file name being opened needs to be changed.
+ * @param inFileName New file name to be displayed
+ */
+void CProgressPalette::SetFileName(const Q3DStudio::CString &inFileName)
+{
+ SendMessageToDescendants(WM_STUDIO_LOADPROGRESS, CProgressView::PROGRESSUPDATE_FILENAME,
+ reinterpret_cast<LPARAM>(&inFileName));
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.h b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.h
new file mode 100644
index 00000000..7d7cb357
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PROGRESS_PALETTE_H
+#define INCLUDED_PROGRESS_PALETTE_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioPaletteBar.h"
+#include "ProgressCallback.h"
+
+//=============================================================================
+/**
+ * Palette for the loading screen
+ */
+class CProgressPalette : public CStudioDialog, public IProgressCallback
+{
+public:
+ CProgressPalette();
+ virtual ~CProgressPalette();
+ virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, CWnd *inParent = nullptr);
+ void SetProgress(long inPercent);
+ void SetFileName(const Q3DStudio::CString &inFileName);
+ void SetActionText(const Q3DStudio::CString &inText);
+};
+#endif // INCLUDED_PROGRESS_PALETTE_H \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.cpp b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.cpp
new file mode 100644
index 00000000..8b7e796c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ProgressView.h"
+#include "WndControl.h"
+#include "StudioApp.h"
+#include "ProgressControl.h"
+
+//==============================================================================
+// Message Maps, etc.
+//==============================================================================
+IMPLEMENT_DYNCREATE(CProgressView, CView)
+
+BEGIN_MESSAGE_MAP(CProgressView, CView)
+//{{AFX_MSG_MAP(CProgressView)
+ON_WM_SIZE()
+ON_WM_ERASEBKGND()
+//}}AFX_MSG_MAP
+ON_MESSAGE(WM_STUDIO_INITIALIZE_PALETTES, OnInitializePalettes)
+ON_MESSAGE(WM_STUDIO_LOADPROGRESS, OnUpdateProgress)
+END_MESSAGE_MAP()
+
+//=============================================================================
+/**
+ * Constructor: Protected because the view is always created dynamically.
+ * You must call Initialize() before trying to use this class.
+ */
+CProgressView::CProgressView()
+ : m_WndControl(nullptr)
+ , m_ProgressControl(nullptr)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CProgressView::~CProgressView()
+{
+ if (m_WndControl) {
+ m_WndControl->DestroyWindow();
+ m_WndControl = nullptr;
+
+ SAFE_DELETE(m_ProgressControl);
+ }
+}
+
+//==============================================================================
+/**
+ * Handles the WM_INITIALUPDATE message. Responsible for preparing the view
+ * before it is displayed for the first time.
+ */
+LRESULT CProgressView::OnInitializePalettes(WPARAM, LPARAM)
+{
+ if (!m_WndControl) {
+ m_ProgressControl = new CProgressControl;
+ m_WndControl = new CWndControl(m_ProgressControl);
+ m_ProgressControl->SetName("Progress Control");
+
+ if (!::IsWindow(m_WndControl->m_hWnd))
+ m_WndControl->CreateEx(0, AfxRegisterWndClass(CS_DBLCLKS, LoadCursor(nullptr, IDC_WAIT),
+ (HBRUSH)GetStockObject(BLACK_BRUSH)),
+ L"LoadView", WS_CHILD | WS_VISIBLE | WS_MAXIMIZE,
+ CRect(0, 0, 200, 200), this, 100);
+ }
+
+ return 0;
+}
+
+//==============================================================================
+/**
+ * Handles the WM_STUDIO_LOADPROGRESS message. Changes text displayed on the
+ * load control, depending on what we are trying to update.
+ * @param inwParam Should be an EProgressMessage to indicate what we are updating
+ * @param inlParam Depends on inwParam. If the message type is PROGRESSUPDATE_PERCENT,
+ * this parameter contains a long value indicating the percent. If the message
+ * type is PROGRESSUPDATE_FILENAME, this parameter contains a pointer to an
+ * Q3DStudio::CString, which is the name of the file that we are loading.
+ * @return 0
+ */
+LRESULT CProgressView::OnUpdateProgress(WPARAM inwParam, LPARAM inlParam)
+{
+ EProgressMessage theMessageType = static_cast<EProgressMessage>(inwParam);
+
+ switch (theMessageType) {
+ // Update the percentage completed
+ case PROGRESSUPDATE_PERCENT: {
+ long thePercent = (long)inlParam;
+ m_ProgressControl->SetProgress(thePercent);
+ } break;
+
+ // Update the name of the file being loaded
+ case PROGRESSUPDATE_FILENAME: {
+ Q3DStudio::CString *theName = reinterpret_cast<Q3DStudio::CString *>(inlParam);
+ m_ProgressControl->SetFileName(*theName);
+ } break;
+
+ // Update the text above the file name (loading or saving)
+ case PROGRESSUPDATE_ACTIONTEXT: {
+ Q3DStudio::CString *theText = reinterpret_cast<Q3DStudio::CString *>(inlParam);
+ m_ProgressControl->SetActionText(*theText);
+ } break;
+
+ // Nothing to do in the default case
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+//=============================================================================
+/**
+ * Required by base class but does nothing since all drawing is handled by the
+ * child control.
+ */
+void CProgressView::OnDraw(CDC *inDC)
+{
+ Q_UNUSED(inDC);
+}
+
+//=============================================================================
+/**
+ * Resizes the wnd control to fill the whole view.
+ */
+void CProgressView::OnSize(UINT inType, int inX, int inY)
+{
+ CView::OnSize(inType, inX, inY);
+ if (::IsWindow(m_WndControl->GetSafeHwnd()))
+ m_WndControl->MoveWindow(0, 0, inX, inY);
+}
+
+//==============================================================================
+/**
+ * Tells the view to erase before redrawing. Overridden because erasing
+ * before each draw produces a flashing effect.
+ * @param inDC the DC to erase on.
+ * @return FALSE.
+ */
+BOOL CProgressView::OnEraseBkgnd(CDC *inDC)
+{
+ Q_UNUSED(inDC);
+ return FALSE;
+}
diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.h b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.h
new file mode 100644
index 00000000..ed023c0c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PROGRESS_VIEW_H
+#define INCLUDED_PROGRESS_VIEW_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CWndControl;
+class CProgressControl;
+class CStudioApp;
+
+//=============================================================================
+/**
+ * Windows view encapsulating the splash screen.
+ */
+class CProgressView : public CView
+{
+public:
+ /// Used to pass messages from the palette, down to this view
+ enum EProgressMessage {
+ PROGRESSUPDATE_PERCENT = 0, ///< Inidicates that the percentage displayed should be updated
+ PROGRESSUPDATE_FILENAME, ///< Indicates that the file name displayed should be updated
+ PROGRESSUPDATE_ACTIONTEXT, ///< Indicates that the text above the file name needs to be
+ ///updated
+ };
+
+ virtual void OnDraw(CDC *inDC);
+ virtual LRESULT OnInitializePalettes(WPARAM inwParam, LPARAM inlParam);
+ virtual LRESULT OnUpdateProgress(WPARAM inwParam, LPARAM inlParam);
+
+protected:
+ CWndControl *m_WndControl;
+ CProgressControl *m_ProgressControl;
+
+ CProgressView(); ///< Constructor is protected because you can only create this view dynamically
+ DECLARE_DYNCREATE(CProgressView)
+ virtual ~CProgressView();
+ afx_msg void OnSize(UINT inType, int inX, int inY);
+ afx_msg BOOL OnEraseBkgnd(CDC *inDC);
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif // INCLUDED_PROGRESS_VIEW_H \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.cpp b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.cpp
new file mode 100644
index 00000000..112631e6
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SplashPalette.h"
+#include "SplashControl.h" // Just for getting the control's size; the view owns the real splash control
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CSplashPalette::CSplashPalette()
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CSplashPalette::~CSplashPalette()
+{
+}
+
+//==============================================================================
+/**
+ * A wrapper around the CMiniFrameWnd::Create() method.
+ * Simplifies the create parameters for the palette bar. Overridden because
+ * the splash screen is different from all the other palettes.
+ * @return The result from the Create() call (FALSE if unsuccessful)
+ */
+BOOL CSplashPalette::Create(CString inTitle, CCreateContext *inCreateContext,
+ CWnd *inParent /* = nullptr */)
+{
+ CString theWndClass = AfxRegisterWndClass(CS_DBLCLKS, ::LoadCursor(nullptr, IDC_ARROW));
+ BOOL theReturnValue;
+
+ // Add the title of the bar to the registry location.
+ m_DialogName = inTitle;
+
+ // Get the rectangle that we want this splash screen to occupy in the middle of the screen
+ CPt theScreenSize = GetAvailableDisplaySize();
+ CSplashControl theSplashControl; // Just for getting the control's size; the view owns the real
+ // splash control
+ CPt theImageSize = theSplashControl.GetSize();
+ long theXPos = theScreenSize.x / 2 - theImageSize.x / 2;
+ long theYPos = theScreenSize.y / 2 - theImageSize.y / 2;
+ CRect theWindowRect(theXPos, theYPos, theXPos + theImageSize.x, theYPos + theImageSize.y);
+
+ // Create the dialog.
+ DWORD theFlags;
+#ifdef DEBUG
+ theFlags = WS_EX_TOOLWINDOW;
+#else
+ theFlags = WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
+#endif
+ // Create the palette bar.
+ theReturnValue = CFrameWnd::CreateEx(theFlags, theWndClass, inTitle, WS_POPUP, theWindowRect,
+ inParent, 0, inCreateContext);
+
+ return theReturnValue;
+}
diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.h b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.h
new file mode 100644
index 00000000..5f11af0c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SPLASH_PALETTE_H
+#define INCLUDED_SPLASH_PALETTE_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioPaletteBar.h"
+
+//=============================================================================
+/**
+ * Palette for the splash screen
+ */
+class CSplashPalette : public CStudioDialog /*CStudioPaletteBar*/
+{
+public:
+ CSplashPalette();
+ virtual ~CSplashPalette();
+ virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, CWnd *inParent = nullptr);
+};
+#endif // INCLUDED_SPLASH_PALETTE_H \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.cpp b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.cpp
new file mode 100644
index 00000000..fd78e604
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "SplashView.h"
+#include "WidgetControl.h"
+#include "StudioApp.h"
+#include "SplashControl.h"
+
+//=============================================================================
+/**
+ * Constructor: Protected because the view is always created dynamically.
+ * You must call Initialize() before trying to use this class.
+ */
+CSplashView::CSplashView(QWidget *parent)
+ : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint)
+ , m_WndControl(nullptr)
+ , m_SplashControl(nullptr)
+{
+ OnInitializePalettes();
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CSplashView::~CSplashView()
+{
+ delete m_WndControl;
+ m_WndControl = nullptr;
+
+ delete m_SplashControl;
+}
+
+//==============================================================================
+/**
+ * Handles the WM_INITIALUPDATE message. Responsible for preparing the view
+ * before it is displayed for the first time.
+ */
+void CSplashView::OnInitializePalettes()
+{
+ if (!m_WndControl) {
+ m_SplashControl = new CSplashControl;
+ m_WndControl = new WidgetControl(m_SplashControl, this);
+ m_SplashControl->SetName("Splash Control");
+
+ setFixedSize(m_WndControl->sizeHint());
+ }
+}
+
+//=============================================================================
+/**
+ * Resizes the wnd control to fill the whole view.
+ */
+void CSplashView::resizeEvent(QResizeEvent *event)
+{
+ Q_UNUSED(event);
+ m_WndControl->setGeometry(rect());
+}
diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.h b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.h
new file mode 100644
index 00000000..28498e95
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SPLASH_VIEW_H
+#define INCLUDED_SPLASH_VIEW_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <QWidget>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class WidgetControl;
+class CSplashControl;
+
+//=============================================================================
+/**
+ * Windows view encapsulating the splash screen.
+ */
+class CSplashView : public QWidget
+{
+public:
+ explicit CSplashView(QWidget *parent = nullptr);
+ ~CSplashView();
+
+protected:
+ void resizeEvent(QResizeEvent *event) override;
+
+public:
+ void OnInitializePalettes();
+
+protected:
+ WidgetControl *m_WndControl;
+ CSplashControl *m_SplashControl;
+};
+
+#endif // INCLUDED_SPLASH_VIEW_H
diff --git a/src/Authoring/Studio/_Win/Studio/stdafx.cpp b/src/Authoring/Studio/_Win/Studio/stdafx.cpp
new file mode 100644
index 00000000..b6cac561
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Studio/stdafx.cpp
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+// stdafx.cpp : source file that includes just the standard includes
+// Studio.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h" \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Studio/stdafx.h b/src/Authoring/Studio/_Win/Studio/stdafx.h
new file mode 100644
index 00000000..8fb2d134
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Studio/stdafx.h
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifdef __cplusplus
+#pragma once
+
+#pragma warning(disable : 4819)
+
+#include "UICMacros.h"
+
+//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define VC_EXTRALEAN // Exclude morerarely-used stuff from Windows headers
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+#define _AFX_ALL_WARNINGS // turns off MFC's hiding of some common and often safely ignored warning
+ // messages
+
+#ifdef DEBUG
+#define CHECK_BOUNDS // CHECK_BOUNDS affects the way an item is retrieved from container objects
+#endif
+
+#if _MSC_VER >= 1400
+#if defined _M_IX86
+#pragma comment( \
+ linker, \
+ "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+#pragma comment( \
+ linker, \
+ "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment( \
+ linker, \
+ "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment( \
+ linker, \
+ "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+//==============================================================================
+// Standard Includes
+//==============================================================================
+#include <stdio.h> // Standard includes MUST come first
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+//==============================================================================
+// STL Includes
+//==============================================================================
+#pragma warning(push, 3) // Temporarily pop to warning level 3 while including standard headers
+#pragma warning(disable : 4018) // Disable mismatched < STL warning
+#include <vector>
+#include <map>
+#include <deque>
+#include <string>
+#include <stack>
+#include <set>
+#include <list>
+#include <utility>
+#include <algorithm>
+#include <stdexcept>
+#include <limits>
+#pragma warning(pop) // Pop out to previous warning level (probably level 4)
+
+//==============================================================================
+// MFC Includes
+//==============================================================================
+#pragma warning(push, 1)
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#include <afxdisp.h> // MFC Automation classes
+#include <afxpriv.h> // AFX Windows Messages (WM_INITIALUPDATE for example)
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#include <atlbase.h>
+#include <atlcom.h>
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+//==============================================================================
+// ATL Includes
+//==============================================================================
+#include "atlbase.h" // For CrystalEdit
+#include "afxtempl.h" // For CrystalEdit
+#include "afxole.h" // For CrystalEdit
+#pragma warning(pop)
+
+// I put these in to help with some of the data model compile times.
+#pragma warning(push)
+#pragma warning(disable : 4100)
+#pragma warning(disable : 4512)
+#pragma warning(disable : 4702)
+#pragma warning(disable : 4996)
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/variant.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/utility.hpp>
+#include <boost/bind.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/signals.hpp>
+#include <boost/signals/connection.hpp>
+#pragma warning(pop)
+
+//==============================================================================
+// Disable certain warnings since warnings are errors
+//==============================================================================
+#pragma warning(disable : 4100) // unreferenced formal parameter
+#pragma warning(disable : 4702) // Unreachable code
+#pragma warning(disable : 4290) // C++ Exception Specification ignored
+#pragma warning(disable : 4514) // Unreferenced inline function
+#pragma warning(disable : 4121) // Alignment of member sensative to packing
+#pragma warning(disable : 4512) // Assignment not generated
+#pragma warning(disable : 4355) // This used in member initializer list.
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4189) // local variable is initialized but not referenced
+
+//==============================================================================
+// Common Includes
+//==============================================================================
+#include "GUIDUtilities.h"
+#include "UICId.h"
+
+//==============================================================================
+// Application Includes (Aug '08 accumulated most popular include files)
+//==============================================================================
+#include "UICString.h"
+#include "UICMath.h"
+#include "StringLoader.h"
+#include "StudioException.h"
+#include "UICExceptions.h"
+#include "Exceptions.h"
+#include "UICObjectCounter.h"
+#include "STLHelpers.h"
+#include "Pt.h"
+#include "Rct.h"
+#include "SafeArray.h"
+#include "PlatformMacros.h"
+#include "PlatformTypes.h"
+#include "Multicaster.h"
+#include "GenericFunctor.h"
+#include "CColor.h"
+#include "InputStream.h"
+#include "OutputStream.h"
+#include "StudioUtils.h"
+#include "StudioDefs.h"
+#include "StudioErrorIDs.h"
+#include "Strings.h"
+#include "StudioPreferences.h"
+#include "Renderer.h"
+#include "StudioObjectTypes.h"
+#include "HotKeys.h"
+#include "Dispatch.h"
+#include "Cmd.h"
+#include "MasterP.h"
+#include "Dialogs.h"
+#include "Views.h"
+#include "ResourceCache.h"
+#include "CmdBatch.h"
+#include "DispatchListeners.h"
+#include "UICFile.h"
+#include "StudioConst.h"
+#include "resource.h"
+#include "StudioProjectSettings.h"
+#include "Preferences.h"
+#include "StudioClipboard.h"
+#include "DropTarget.h"
+#include "ContextMenu.h"
+#include "TextButton.h"
+
+#include "StudioPrefixWin32.h"
+
+//==============================================================================
+// Common Includes
+//==============================================================================
+#include "Resource.h"
+
+//==============================================================================
+// OpenGL Includes
+//==============================================================================
+#include <GL/gl.h>
+
+#define UIC_LITTLE_ENDIAN
+
+#define SAFE_DELETE(ptr) \
+ if ((ptr) != nullptr) { \
+ delete (ptr); \
+ (ptr) = nullptr; \
+ }
+#endif
diff --git a/src/Authoring/Studio/_Win/UI/ContextMenu.cpp b/src/Authoring/Studio/_Win/UI/ContextMenu.cpp
new file mode 100644
index 00000000..6aedc806
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ContextMenu.cpp
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2001 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "ContextMenu.h"
+#include "StringLoader.h"
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CContextMenu::CContextMenu()
+ : m_SelectedOption(-1)
+ , m_IndexBase(0)
+{
+ m_Menu = ::CreatePopupMenu();
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CContextMenu::~CContextMenu()
+{
+ ::DestroyMenu(m_Menu);
+}
+
+//=============================================================================
+/**
+ * Display the popup menu and perform the actions for whatever choice the
+ * user makes.
+ * @param inLocation the screen coordinates of the location to display this menu.
+ * @param inParentWindow the window to attach this menu to.
+ */
+long CContextMenu::DoPopup(CPt inLocation, HWND inParentWindow)
+{
+ // Allow derived classes to update the menu state
+ Update();
+
+ ::SetCursor(::LoadCursor(nullptr, IDC_ARROW));
+
+ // Display the menu and get the user's input
+ unsigned int theCommandID = (unsigned int)::TrackPopupMenuEx(
+ m_Menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTBUTTON,
+ inLocation.x, inLocation.y, inParentWindow, nullptr);
+
+ // If an option was selected then get the performer for that option and execute it.
+ m_SelectedOption = theCommandID - 1;
+ if (m_SelectedOption >= 0) {
+ CContextMenuPerformer *thePerformer = GetSelectedMenuPerformer(m_SelectedOption);
+ if (thePerformer != nullptr) {
+ thePerformer->OnOptionSelected();
+ }
+ }
+
+ return m_SelectedOption;
+}
+
+//=============================================================================
+/**
+ * Append a separator to the list of items in this menu.
+ */
+void CContextMenu::AddSeparator()
+{
+ ::AppendMenu(m_Menu, MF_SEPARATOR, 0, nullptr);
+}
+
+//=============================================================================
+/**
+ * Append the option onto the end of this menu.
+ * @param inOptionNameStringID ID indicating the display name for the option.
+ * @param inPerformer the performer to be called if this option is selected.
+ * @param inIsEnabled false if the option is to be grayed out and disabled.
+ */
+void CContextMenu::AddOption(int inOptionNameStringID, CContextMenuPerformer *inPerformer,
+ bool inIsEnabled /* = true */)
+{
+ Q3DStudio::CString theOptionName(::LoadResourceString(inOptionNameStringID));
+ AddOption(theOptionName, inPerformer, inIsEnabled);
+}
+
+//=============================================================================
+/**
+ * Append the option onto the end of this menu.
+ * @param inOptionName the display name for the option.
+ * @param inPerformer the performer to be called if this option is selected.
+ * @param inIsEnabled false if the option is to be grayed out and disabled.
+ */
+void CContextMenu::AddOption(const Q3DStudio::CString &inOptionName,
+ CContextMenuPerformer *inPerformer, bool inIsEnabled /*= true */)
+{
+ size_t theIndex = m_IndexBase; // start from a base, so that submenu items can be distinguished
+
+ long theFlags = MF_STRING;
+ if (!inIsEnabled)
+ theFlags |= MF_GRAYED;
+
+ m_Performers.push_back(inPerformer);
+ m_Options.push_back(inOptionName);
+ CContextMenu *theSubMenu = (inPerformer ? inPerformer->GetSubMenu() : nullptr);
+ if (!theSubMenu)
+ theIndex += m_Performers.size();
+ else // if performer has a submenu.
+ {
+ theIndex = (UINT)theSubMenu->GetMenuHandle();
+ theFlags |= MF_POPUP;
+ }
+
+ ::AppendMenuW(m_Menu, theFlags, theIndex, inOptionName);
+}
+
+//=============================================================================
+/**
+ * Remove all options from the menu.
+ */
+void CContextMenu::Clear()
+{
+ long theCount = ::GetMenuItemCount(m_Menu);
+ for (long theIndex = theCount - 1; theIndex >= 0; theIndex--)
+ ::DeleteMenu(m_Menu, theIndex, MF_BYPOSITION);
+
+ m_Performers.clear();
+ m_Options.clear();
+}
+
+//=============================================================================
+/**
+ * Delete all the performers on this object.
+ * This is an ease of use method for subclasses if they allocated their
+ * performers on the heap. This just deletes all of them and clears the list.
+ */
+void CContextMenu::DeletePerformers()
+{
+ TPerformerList::iterator thePos = m_Performers.begin();
+ for (; thePos != m_Performers.end(); ++thePos) {
+ delete (*thePos);
+ }
+ m_Performers.clear();
+}
+
+//=============================================================================
+/**
+ * Adds or removes a check mark from the specified item.
+ * @param inIndex Index of context menu item to be edited
+ * @param inChecked true to set a check, false to remove a check
+ */
+void CContextMenu::SetCheck(long inIndex, bool inChecked)
+{
+ long theFlags = MF_BYPOSITION;
+ theFlags |= inChecked ? MF_CHECKED : MF_UNCHECKED;
+
+ long theActualIndex = inIndex;
+ for (long thePos = 0; thePos < (long)::GetMenuItemCount(m_Menu) && thePos <= inIndex;
+ ++thePos) {
+ // Account for separators that doesn't "contribute" to the number of performers.
+ MENUITEMINFO theMenuInfo;
+ ZeroMemory(&theMenuInfo, sizeof(MENUITEMINFO));
+ theMenuInfo.cbSize = sizeof(MENUITEMINFO);
+ theMenuInfo.fMask = MIIM_TYPE;
+ ::GetMenuItemInfo(m_Menu, thePos, TRUE, &theMenuInfo);
+ if (theMenuInfo.fType & MFT_SEPARATOR)
+ ++theActualIndex;
+ }
+ ::CheckMenuItem(m_Menu, theActualIndex, theFlags);
+}
+
+//=============================================================================
+/**
+ * Set all the menu items to being unchecked.
+ * This will uncheck any items that are currently checked.
+ */
+void CContextMenu::ClearChecked()
+{
+ for (long thePos = 0; thePos < (long)::GetMenuItemCount(m_Menu); ++thePos)
+ ::CheckMenuItem(m_Menu, thePos, MF_BYPOSITION | MF_UNCHECKED);
+}
+
+//=============================================================================
+/**
+ * Gets the string located at a certain index in the context menu list. Index
+ * is zero-based.
+ * @param inIndex zero-based index of the item whose string you want
+ * @return the string at the specified index
+ */
+Q3DStudio::CString CContextMenu::GetStringAt(long inIndex)
+{
+ Q3DStudio::CString theString;
+ if (inIndex >= 0 && inIndex < (long)m_Options.size())
+ theString = m_Options.at(inIndex);
+ return theString;
+}
+
+//=============================================================================
+/**
+ * @return the number of items in this context menu
+ */
+long CContextMenu::GetItemCount()
+{
+ return (long)m_Options.size();
+}
+
+//=============================================================================
+/**
+ * Override this to set enable state of options before the menu pops up
+ */
+void CContextMenu::Update()
+{
+}
+
+static inline long GetEnableMenuItemFlags(bool inEnabledState)
+{
+ return MF_BYPOSITION | (inEnabledState ? (MF_ENABLED) : (MF_GRAYED));
+}
+
+void CContextMenu::EnableOptionByIndex(long inIndex, bool inEnabledState /*= true*/)
+{
+ if (inIndex >= 0 && inIndex < (long)m_Options.size())
+ ::EnableMenuItem(m_Menu, inIndex, GetEnableMenuItemFlags(inEnabledState));
+}
+
+void CContextMenu::EnableOption(const Q3DStudio::CString &inOptionName, bool inEnabledState)
+{
+ long theCount = (long)m_Options.size();
+ for (long theIndex = 0; theIndex < theCount; ++theIndex) {
+ if (m_Options[theIndex] == inOptionName) {
+ ::EnableMenuItem(m_Menu, theIndex, GetEnableMenuItemFlags(inEnabledState));
+ break;
+ }
+ }
+}
+
+void CContextMenu::EnableOption(unsigned int inOptionNameStringID, bool inEnabledState)
+{
+ Q3DStudio::CString theOptionName(::LoadResourceString(inOptionNameStringID));
+ EnableOption(theOptionName, inEnabledState);
+}
+
+//=============================================================================
+/**
+ * Find the menu performer associated with this index, recursing down any submenu if necessary.
+ * @param inIndex index of the menu performer
+ */
+CContextMenuPerformer *CContextMenu::GetSelectedMenuPerformer(long inIndex)
+{
+ if (inIndex - m_IndexBase < static_cast<long>(m_Performers.size())) {
+ m_SelectedOption =
+ inIndex - m_IndexBase; // update this for any references to the selected option
+ return m_Performers.at(m_SelectedOption);
+ }
+ // if not found, recurse down submenus
+ CContextMenuPerformer *theResult = nullptr;
+ TPerformerList::iterator theIter = m_Performers.begin();
+ for (; theIter != m_Performers.end() && !theResult; ++theIter) {
+ CContextMenu *theSubMenu = (*theIter)->GetSubMenu();
+ if (theSubMenu)
+ theResult = theSubMenu->GetSelectedMenuPerformer(inIndex);
+ }
+ return theResult;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/UI/ControlButton.cpp b/src/Authoring/Studio/_Win/UI/ControlButton.cpp
new file mode 100644
index 00000000..d99ce639
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ControlButton.cpp
@@ -0,0 +1,471 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "resource.h"
+#include "ControlButton.h"
+#include "MemoryDC.h"
+#include "WinUtils.h"
+
+//==============================================================================
+/*
+ * Constructor: Initializes the object.
+ */
+CControlButton::CControlButton()
+ : m_ImageUp(nullptr)
+ , m_ImageDown(nullptr)
+ , m_ImageDisabled(nullptr)
+ , m_ImageActive(nullptr)
+ , m_ImageMouseTrack(nullptr)
+ , m_ImageLimbo(nullptr)
+ , m_ActiveFlag(FALSE)
+ , m_HotTrackFlag(FALSE)
+ , m_MouseOverFlag(FALSE)
+ , m_ActiveDepressedFlag(FALSE)
+ , m_LimboEnabled(FALSE)
+ , m_LimboFlag(FALSE)
+ , m_SimpleFrame(TRUE)
+ , m_DrawFrame(TRUE)
+ , m_DepressFlag(FALSE)
+ , m_3DColorsFlag(FALSE)
+{
+ m_ImageOffset = CPoint(0, 0);
+ m_FillColor = GetSysColor(COLOR_WINDOW);
+ m_TransparentColor = RGB(255, 0, 255);
+ m_FillColor = GetSysColor(COLOR_3DFACE);
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+CControlButton::~CControlButton()
+{
+}
+
+BEGIN_MESSAGE_MAP(CControlButton, CButton)
+//{{AFX_MSG_MAP(CControlButton)
+ON_WM_MOUSEMOVE()
+ON_WM_ERASEBKGND()
+//}}AFX_MSG_MAP
+ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * Method to create the button
+ *
+ * @param inStyle Window style for the button
+ * @param inRect Bounding rectangle for the button
+ * @param inParentWnd Parent window for the button
+ * @param inID Child window ID for the button
+ * @param inDepressFlag
+ * @param inLimboEnabled Set to TRUE if this is a tri-state button (defaults to false).
+ *The third state is referred to as "limbo".
+ * Then use SetLimbo() to enter and leave the limbo state.
+ *
+ * @return Returns TRUE if the button was created
+ */
+BOOL CControlButton::Create(DWORD inStyle, const RECT &inRect, CWnd *inParentWnd, short inID,
+ BOOL inDepressFlag, BOOL inLimboEnabled)
+{
+ m_DepressFlag = inDepressFlag;
+ m_LimboEnabled = inLimboEnabled;
+
+ return CButton::Create(L"", inStyle /*| WS_BORDER*/ | BS_OWNERDRAW, inRect, inParentWnd, inID);
+}
+
+//==============================================================================
+/**
+ * Adds images to the button for the different button states.
+ * @param inTransparentColor RGB value of the transparency color used within the
+ *bitmaps. If there is no transparency color,
+ * set this to a value that does not appear in any of
+ *the images.
+ * @param inImageUp Image for the up state
+ * @param inImageDown Image for the down state
+ * @param inImageDisabled Image for the disabled state
+ * @param inImageActive Image for the active state
+ * @param inImageMouseTrack Image for hot mouse tracking
+ * @param inImageLimbo Image for "limbo" state (used for tri-state buttons)
+ */
+void CControlButton::AddImages(COLORREF inTransparentColor, short inImageUp, short inImageDown,
+ short inImageDisabled, short inImageActive, short inImageMouseTrack,
+ short inImageLimbo)
+{
+ if (inImageUp != 0)
+ m_ImageUp = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageUp),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ // You always need to have at least one valid image for a button
+ ASSERT(m_ImageUp != nullptr);
+
+ if (inImageDown != 0)
+ m_ImageDown = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageDown),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ if (inImageDisabled != 0)
+ m_ImageDisabled =
+ (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageDisabled),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ if (inImageActive != 0)
+ m_ImageActive = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageActive),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ if (inImageMouseTrack != 0)
+ m_ImageMouseTrack =
+ (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageMouseTrack),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ if (inImageLimbo != 0)
+ m_ImageLimbo = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageLimbo),
+ IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
+
+ m_TransparentColor = inTransparentColor;
+
+ if (IsWindow(m_hWnd))
+ this->Redraw();
+}
+
+//==============================================================================
+/**
+ * SetImageOffset
+ *
+ * Sets an image drawing offset
+ *
+ * @param inOffset Offset for image from (0,0)
+ */
+void CControlButton::SetImageOffset(CPoint inOffset)
+{
+ m_ImageOffset = inOffset;
+}
+
+//==============================================================================
+/**
+ * SetActiveDepressed
+ *
+ * Sets the active depressed flag. If TRUE and this control is set to active,
+ * then the image will be displayed in a depressed state (for toggle items).
+ *
+ * @param inActiveDepressedFlag TRUE if the active state should be depressed
+ */
+void CControlButton::SetActiveDepressed(BOOL inActiveDepressedFlag)
+{
+ m_ActiveDepressedFlag = inActiveDepressedFlag;
+}
+
+//==============================================================================
+/**
+ * SetActive
+ *
+ * Sets the active state for the button
+ *
+ * @param inActiveState Active state for the button
+ */
+void CControlButton::SetActive(BOOL inActiveFlag)
+{
+ m_ActiveFlag = inActiveFlag;
+
+ if (IsWindow(m_hWnd))
+ this->Redraw();
+}
+
+//==============================================================================
+/**
+ * GetActive
+ *
+ * Gets the active state for the button
+ *
+ * @param None
+ *
+ * @return Active state for the button
+ */
+BOOL CControlButton::GetActive()
+{
+ return m_ActiveFlag;
+}
+
+//==============================================================================
+/**
+ * DrawItem
+ *
+ * Handle the owner drawn button
+ *
+ * @param inDrawItemStruct DRAWITEMSTRUCT structure
+ */
+void CControlButton::DrawItem(LPDRAWITEMSTRUCT inDrawItemStruct)
+{
+ CDC *theDC;
+ CMemoryDC theMemDC;
+ BOOL theEnabledFlag;
+ BOOL theDownStateFlag;
+ HBITMAP theBitmap = m_ImageUp;
+ CRect theRect;
+
+ theDC = GetDC();
+
+ // Get the bounding client rectangle
+ GetClientRect(theRect);
+
+ theMemDC.Create(theDC, theRect);
+
+ theDownStateFlag = (inDrawItemStruct->itemState & ODS_SELECTED);
+
+ // Is this window enabled?
+ theEnabledFlag = IsWindowEnabled();
+
+ if (m_ActiveFlag)
+ theBitmap = m_ImageActive;
+
+ if (m_MouseOverFlag)
+ if (m_ImageMouseTrack != 0)
+ theBitmap = m_ImageMouseTrack;
+
+ if (!theEnabledFlag) {
+ // Disabled
+ if (m_ImageDisabled != 0)
+ theBitmap = m_ImageDisabled;
+ } else {
+ // Window is enabled
+ if (theDownStateFlag)
+ if (m_ImageDown != 0)
+ theBitmap = m_ImageDown;
+ }
+
+ // If the button has limbo enabled, and it in limbo state, it overrides any previous button
+ // settings
+ if (m_LimboEnabled && m_LimboFlag)
+ if (m_ImageLimbo != 0)
+ theBitmap = m_ImageLimbo;
+
+ // Fill the background color
+ theMemDC.FillSolidRect(theRect, m_FillColor);
+
+ // Draw the bitmap if it exists
+ if (theBitmap)
+ CWinUtils::DrawTransparentBitmap(
+ &theMemDC, m_ImageOffset.x + theDownStateFlag * m_DepressFlag,
+ m_ImageOffset.y + theDownStateFlag * m_DepressFlag, theBitmap, m_TransparentColor);
+
+ // Hot tracking the mouse over the button?
+ if (m_HotTrackFlag) {
+ if (m_DepressFlag) {
+ if (theDownStateFlag)
+ DrawButtonFrame((CDC *)&theMemDC, &theRect, TRUE);
+ else if (m_MouseOverFlag)
+ DrawButtonFrame((CDC *)&theMemDC, &theRect, FALSE);
+ } else {
+ if (m_MouseOverFlag)
+ DrawButtonFrame((CDC *)&theMemDC, &theRect, FALSE);
+ }
+ } else {
+ // Draw the frame around the button
+ if (!m_ActiveFlag)
+ DrawButtonFrame((CDC *)&theMemDC, &theRect, theDownStateFlag * m_DepressFlag);
+ }
+
+ theMemDC.Release();
+
+ ReleaseDC(theDC);
+}
+
+//==============================================================================
+/**
+ * DrawButtonFrame
+ *
+ * Draw the button frame
+ *
+ * @param inDC Device context for drawing
+ * @param inRect Bounding rectangle for the button frame
+ * @param inDownFlag If TRUE, the button is down
+ */
+void CControlButton::DrawButtonFrame(CDC *inDC, CRect *inRect, BOOL inDownFlag)
+{
+ if (m_DrawFrame) {
+ COLORREF theShadowColor = GetSysColor(COLOR_3DSHADOW);
+ COLORREF theHiliteColor = GetSysColor(COLOR_3DHIGHLIGHT);
+
+ if (inDownFlag) {
+ theShadowColor = GetSysColor(COLOR_3DHIGHLIGHT);
+ theHiliteColor = GetSysColor(COLOR_3DSHADOW);
+ }
+
+ CRect theFrameRect;
+
+ theFrameRect.CopyRect(inRect);
+
+ if (m_SimpleFrame) {
+ inDC->Draw3dRect(&theFrameRect, theHiliteColor, theShadowColor);
+ } else {
+ if (inDownFlag) {
+ theFrameRect.right--;
+ theFrameRect.bottom--;
+
+ inDC->Draw3dRect(&theFrameRect, theHiliteColor, theShadowColor);
+ } else {
+ // the button is up
+ theFrameRect.right--;
+ theFrameRect.bottom--;
+
+ inDC->Draw3dRect(&theFrameRect, theHiliteColor, theShadowColor);
+
+ inDC->MoveTo(theFrameRect.right, theFrameRect.top);
+ inDC->LineTo(theFrameRect.right, theFrameRect.bottom);
+ inDC->LineTo(theFrameRect.left, theFrameRect.bottom);
+ }
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * SetHotTrack
+ *
+ * Set the hot track (mouse over) flag
+ *
+ * @param inHotTrackFlag Hot tracking flag
+ */
+void CControlButton::SetHotTrack(BOOL inHotTrackFlag)
+{
+ m_HotTrackFlag = inHotTrackFlag;
+
+ if (IsWindow(m_hWnd))
+ this->Redraw();
+}
+
+//==============================================================================
+/**
+ * OnMouseMove
+ *
+ * Handle the WM_MOUSEMOVE message
+ *
+ * @param inFlags Flags for WM_MOUSEMOVE
+ * @param inPoint Cursor position in client coordinates
+ */
+void CControlButton::OnMouseMove(UINT inFlags, CPoint inPoint)
+{
+ CButton::OnMouseMove(inFlags, inPoint);
+
+ if (!m_MouseOverFlag) {
+ this->TrackMouse();
+ m_MouseOverFlag = TRUE;
+
+ this->Redraw();
+ }
+}
+
+//==============================================================================
+/**
+ * OnMouseMove
+ *
+ * Handle the WM_MOUSELEAVE message
+ *
+ * @param inwParam WPARAM for the WM_MOUSELEAVE message
+ * @param inlParam LPARAM for the WM_MOUSELEAVE message
+ *
+ * @param Return code - returns TRUE if this message is processed.
+ */
+LRESULT CControlButton::OnMouseLeave(WPARAM inwParam, LPARAM inlParam)
+{
+ Q_UNUSED(inwParam);
+ Q_UNUSED(inlParam);
+
+ m_MouseOverFlag = FALSE;
+
+ this->TrackMouse(FALSE);
+
+ this->Redraw();
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * TrackMouse
+ *
+ * Register for the WM_MOUSELEAVE message to determine when
+ * the mouse leaves this button.
+ *
+ * @param inTrackEnableFlag - TRUE/FALSE depending on whether we want to track the mouse
+ *event state.
+ */
+void CControlButton::TrackMouse(BOOL inTrackEnableFlag)
+{
+ TRACKMOUSEEVENT theTrackMouseEvent;
+
+ memset(&theTrackMouseEvent, 0, sizeof(theTrackMouseEvent));
+
+ theTrackMouseEvent.cbSize = sizeof(theTrackMouseEvent);
+ theTrackMouseEvent.dwFlags = TME_LEAVE;
+ if (!inTrackEnableFlag)
+ theTrackMouseEvent.dwFlags |= TME_CANCEL;
+ theTrackMouseEvent.hwndTrack = m_hWnd;
+
+ _TrackMouseEvent(&theTrackMouseEvent);
+}
+
+//==============================================================================
+/**
+ * Redraw
+ *
+ * Invalidate and update the button
+ *
+ * @param None
+ */
+void CControlButton::Redraw()
+{
+ // Invalidate and update the window
+ InvalidateRect(nullptr, TRUE);
+ UpdateWindow();
+}
+
+//==============================================================================
+/**
+ * Handles the WM_ERASEBKGND message. This function is overridden so that we
+ * can prevent the background from being erased. When we draw the button, the
+ * background is filled in with the appropriate color. Actually erasing the
+ * background before a draw was producing flickering.
+ *
+ * @param pDC Not used.
+ */
+BOOL CControlButton::OnEraseBkgnd(CDC *pDC)
+{
+ Q_UNUSED(pDC);
+ return 1;
+}
diff --git a/src/Authoring/Studio/_Win/UI/ControlButton.h b/src/Authoring/Studio/_Win/UI/ControlButton.h
new file mode 100644
index 00000000..6f168cb2
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ControlButton.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#if !defined(AFX_CONTROLBUTTON_H__6B61A743_FB7E_11D4_A87A_005004D48D91__INCLUDED_)
+#define AFX_CONTROLBUTTON_H__6B61A743_FB7E_11D4_A87A_005004D48D91__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+/////////////////////////////////////////////////////////////////////////////
+// CControlButton window
+
+class CControlButton : public CButton
+{
+ // Construction
+public:
+ CControlButton();
+
+ // Attributes
+public:
+protected:
+ HBITMAP m_ImageUp, m_ImageDown, m_ImageDisabled, m_ImageActive, m_ImageMouseTrack,
+ m_ImageLimbo; // resource bitmap values for various button states
+ BOOL m_DepressFlag, m_3DColorsFlag; // drawing flags
+ BOOL m_ActiveFlag; // TRUE if the button is active (ie - selected)
+ BOOL m_ActiveDepressedFlag; // TRUE if the active state should be drawn depressed
+ CPoint m_ImageOffset; // Image offset from (0,0)
+ BOOL m_MouseOverFlag; // TRUE if the mouse is currently over this button
+ BOOL m_HotTrackFlag; // TRUE if the mouse should be hot-tracked
+ BOOL m_SimpleFrame; // TRUE if the button is a simple frame
+ BOOL m_DrawFrame; // TRUE if the frame around the button should be drawn
+ BOOL m_LimboEnabled; ///< TRUE if this button is capable of being in limbo (decided at creation
+ ///time)
+ BOOL m_LimboFlag; ///< TRUE if the button is currently in limbo state
+ COLORREF m_FillColor;
+ COLORREF m_TransparentColor;
+
+ // Operations
+public:
+ void AddImages(COLORREF inTransparentColor, short inImageUp, short inImageDown = 0,
+ short inImageDisabled = 0, short inImageActive = 0, short inImageMouseTrack = 0,
+ short inImageLimbo = 0);
+
+ BOOL Create(DWORD inStyle, const RECT &inRect, CWnd *inParentWnd, short inID,
+ BOOL inDepressFlag = TRUE, BOOL inTriState = FALSE);
+
+ BOOL GetActive();
+
+ void SetActive(BOOL inActiveFlag);
+ void SetActiveDepressed(BOOL inActiveDepressedFlag);
+ /// Sets the "limbo" state of the button. Usefully for making tri-state buttons. Limbo state
+ /// only works if the limbo flag was set during creation.
+ void SetLimbo(BOOL inLimboFlag) { m_LimboFlag = inLimboFlag; }
+ /// Returns TRUE if the button is in "limbo" state
+ BOOL GetLimbo() { return m_LimboFlag; }
+ void SetHotTrack(BOOL inHotTrackFlag);
+ void SetImageOffset(CPoint inOffset);
+ void SetDrawFrame(BOOL inDrawFrame) { m_DrawFrame = inDrawFrame; }
+ /// Use this function to manually set the fill color behind the button. Use this if you notice
+ /// that the wrong color is showing up.
+ void SetFillColor(COLORREF inColor) { m_FillColor = inColor; }
+protected:
+ void DrawButtonFrame(CDC *inDC, CRect *inRect, BOOL inDownFlag);
+ void Redraw();
+ void TrackMouse(BOOL inTrackEnableFlag = TRUE);
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CControlButton)
+public:
+ virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ virtual ~CControlButton();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CControlButton)
+ afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ afx_msg BOOL OnEraseBkgnd(CDC *pDC);
+ //}}AFX_MSG
+ afx_msg LRESULT OnMouseLeave(WPARAM inwParam, LPARAM inlParam);
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CONTROLBUTTON_H__6B61A743_FB7E_11D4_A87A_005004D48D91__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/CrashDlg.cpp b/src/Authoring/Studio/_Win/UI/CrashDlg.cpp
new file mode 100644
index 00000000..13277385
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/CrashDlg.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "MainFrm.h"
+#include "CrashDlg.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrashDlg dialog
+
+CCrashDlg::CCrashDlg(CWnd *pParent /*=nullptr*/)
+ : CDialog(CCrashDlg::IDD, pParent)
+ , m_Filename(_T(""))
+{
+ //{{AFX_DATA_INIT(CCrashDlg)
+ m_Header = _T("");
+ //}}AFX_DATA_INIT
+
+ m_MediumFont2.CreatePointFont(88, CString(CStudioPreferences::GetFontFaceName()));
+
+ m_Color_Background = CStudioPreferences::GetDarkBaseColor();
+ m_Color_Text = CStudioPreferences::GetMasterColor();
+ m_Color_Gray = CStudioPreferences::GetNormalColor();
+ m_Color_Dark = CStudioPreferences::GetInactiveColor();
+}
+
+void CCrashDlg::DoDataExchange(CDataExchange *pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CCrashDlg)
+ DDX_Control(pDX, IDC_CRASHICON, m_CrashIcon);
+ DDX_Text(pDX, IDC_HEADER, m_Header);
+ DDX_Text(pDX, IDC_HEADER2, m_FilenameSaved);
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CCrashDlg, CDialog)
+//{{AFX_MSG_MAP(CCrashDlg)
+ON_BN_CLICKED(IDEXIT, OnExit)
+//}}AFX_MSG_MAP
+// ON_STN_CLICKED(IDC_HEADER, &CCrashDlg::OnStnClickedHeader)
+ON_WM_ERASEBKGND()
+ON_WM_CTLCOLOR()
+ON_WM_DESTROY()
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * Set the description of the crash.
+ * @param inErrorMessage the error message.
+ */
+//==============================================================================
+void CCrashDlg::SetErrorMessage(CString inErrorMessage)
+{
+ m_ErrorMessage = inErrorMessage;
+}
+
+//==============================================================================
+/**
+ * Set the project filename saved
+ * @param inFilename the filename of the crashed project
+ */
+//==============================================================================
+void CCrashDlg::SetFilename(CString inFilename)
+{
+ m_Filename = inFilename;
+}
+
+//==============================================================================
+/**
+ * Set the stack trace for the crash.
+ * @param inStackTrace the stack trace.
+ */
+//==============================================================================
+void CCrashDlg::SetStackTrace(CString inStackTrace)
+{
+ m_StackTrace = inStackTrace;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrashDlg message handlers
+
+void CCrashDlg::OnExit()
+{
+ this->EndDialog(0);
+ _exit(EXIT_FAILURE);
+}
+
+void CCrashDlg::SplitLongPath(int controlId, CString &text)
+{
+
+ // Get the device context of your control.
+ CDC *dc = GetDlgItem(controlId)->GetDC();
+ CRect filenameTextRect;
+ GetDlgItem(controlId)->GetClientRect(filenameTextRect);
+
+ HGDIOBJ hOldFont = dc->SelectObject(&m_MediumFont2);
+
+ CRect tmpStringRect(0, 0, 0, 0);
+ CString workingString = text;
+
+ CString tmpString;
+ std::vector<int> insertPosition;
+ int previousOffset = 0;
+
+ for (int i = 0; i < workingString.GetLength(); ++i) {
+ tmpString = workingString.Mid(previousOffset, i - previousOffset);
+ dc->DrawText(tmpString, &tmpStringRect, DT_CALCRECT);
+ if (tmpStringRect.Width() + 5 > filenameTextRect.Width()) {
+ previousOffset = i;
+ insertPosition.push_back(i - 1);
+ }
+ }
+
+ // adds in all the \n
+ for (int i = (int)insertPosition.size() - 1; i >= 0; --i) {
+ text.Insert(insertPosition[i], '\n');
+ }
+
+ dc->SelectObject(hOldFont);
+}
+
+BOOL CCrashDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_Brush.CreateSolidBrush(m_Color_Background);
+ GetDlgItem(IDC_HEADER)->SetFont(&m_MediumFont2);
+ GetDlgItem(IDC_HEADER2)->SetFont(&m_MediumFont2);
+
+ // m_Header = ::LoadResourceString( IDS_ERROR_MSGPASSING ).GetMulti( );
+ m_Header = m_ErrorMessage;
+ m_FilenameSaved = m_Filename;
+
+ CString theTitle = ::LoadResourceString(IDS_ERROR_MSGTITLE);
+ this->SetWindowText(theTitle);
+
+ // Show the exclamation point icon
+ m_CrashIcon.SetIcon(::LoadIcon(nullptr, IDI_ERROR));
+
+ SplitLongPath(IDC_HEADER2, m_FilenameSaved);
+ SplitLongPath(IDC_HEADER, m_Header);
+
+ this->UpdateData(FALSE);
+
+ return TRUE;
+}
+
+BOOL CCrashDlg::OnEraseBkgnd(CDC *pDC)
+{
+ CRect theClientRect;
+ GetClientRect(&theClientRect);
+ pDC->FillSolidRect(theClientRect, m_Color_Background);
+
+ return TRUE;
+}
+
+HBRUSH CCrashDlg::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT)
+{
+ int theCtrlID = pWnd->GetDlgCtrlID();
+ if (theCtrlID == IDREPORT || theCtrlID == IDEXIT || theCtrlID == IDC_LINE_CRASHDLG) {
+ pDC->SetBkMode(TRANSPARENT); // for area just behind the text
+ pDC->SetTextColor(m_Color_Text);
+ } else if (theCtrlID == IDC_HEADER || theCtrlID == IDC_HEADER2) {
+ pDC->SetBkMode(TRANSPARENT); // for area just behind the text
+ pDC->SetTextColor(m_Color_Gray);
+ }
+
+ return m_Brush;
+}
+
+void CCrashDlg::OnDestroy()
+{
+ CDialog::OnDestroy();
+
+ m_Brush.DeleteObject();
+}
diff --git a/src/Authoring/Studio/_Win/UI/CrashDlg.h b/src/Authoring/Studio/_Win/UI/CrashDlg.h
new file mode 100644
index 00000000..75f5765c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/CrashDlg.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_CRASH_DIALOG_H
+#define INCLUDED_CRASH_DIALOG_H
+#include "afxwin.h"
+#include <string.h>
+
+#pragma once
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrashDlg dialog
+
+class CCrashDlg : public CDialog
+{
+ // Construction
+public:
+ CCrashDlg(CWnd *pParent = nullptr); // standard constructor
+
+ // Dialog Data
+ //{{AFX_DATA(CCrashDlg)
+ enum { IDD = IDD_CRASHDLG };
+ CStatic m_CrashIcon;
+ CString m_Header;
+ //}}AFX_DATA
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CCrashDlg)
+protected:
+ virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ void SetErrorMessage(CString inErrorMessage);
+ void SetFilename(CString inFilename);
+ void SetStackTrace(CString inStackTrace);
+ void SplitLongPath(int controlId, CString &text);
+
+protected:
+ CString m_ErrorMessage;
+ CString m_FilenameSaved;
+ CString m_StackTrace;
+
+ COLORREF m_Color_Background;
+ COLORREF m_Color_Text;
+ COLORREF m_Color_Gray;
+ COLORREF m_Color_Dark;
+ CBrush m_Brush;
+ CFont m_MediumFont2;
+
+ // Generated message map functions
+ //{{AFX_MSG(CCrashDlg)
+ afx_msg void OnSave();
+ afx_msg void OnExit();
+ afx_msg void OnDestroy();
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+public:
+ afx_msg BOOL OnEraseBkgnd(CDC *pDC);
+ afx_msg HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor);
+ CString m_Filename;
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // INCLUDED_CRASH_DIALOG_H
diff --git a/src/Authoring/Studio/_Win/UI/EditCameraBar.cpp b/src/Authoring/Studio/_Win/UI/EditCameraBar.cpp
new file mode 100644
index 00000000..7827ee93
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/EditCameraBar.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "EditCameraBar.h"
+#include "MainFrm.h"
+#include "SceneView.h"
+#include "StringLoader.h"
+#include "StudioPreferences.h"
+#include "StudioApp.h"
+#include "IStudioRenderer.h"
+
+#include <QComboBox>
+#include <QLabel>
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CEditCameraBar::CEditCameraBar(QWidget* parent)
+ : QToolBar(parent)
+ , m_SceneView(nullptr)
+ , m_ActiveCameraIndex(-1)
+{
+ OnCustomizeToolbar();
+ auto activated = static_cast<void(QComboBox::*)(int)>(&QComboBox::activated);
+ connect(m_CameraSelector, activated, this, &CEditCameraBar::OnCameraChanged);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CEditCameraBar::~CEditCameraBar()
+{
+ delete m_CameraSelector;
+ delete m_CameraText;
+}
+
+//==============================================================================
+/**
+ * Setup the list of edit cameras into the camera combo box
+ * @param inCameras the container that holds the edit cameras
+ */
+void CEditCameraBar::SetupCameras()
+{
+ m_CameraSelector->clear();
+ Q3DStudio::IStudioRenderer &theRenderer = g_StudioApp.GetRenderer();
+ QStringList theCameraNames;
+ theRenderer.GetEditCameraList(theCameraNames);
+ int idx = 1;
+ for (const QString &str : qAsConst(theCameraNames)) {
+ m_CameraSelector->addItem(str, QVariant((int)idx));
+ idx++;
+ }
+
+ m_CameraSelector->addItem("--------------------------");
+ m_CameraSelector->setItemData(m_CameraSelector->count() - 1, -1); // set to an invalid pointer
+ m_CameraSelector->addItem(::LoadResourceString(IDS_SCENE_CAMERA_VIEW).toQString());
+ m_CameraSelector->setItemData(m_CameraSelector->count() - 1, 0);
+
+ long thePreferredView = CStudioPreferences::GetPreferredStartupView();
+ long theNumItems = m_CameraSelector->count();
+ if (thePreferredView == -1) // deployment view
+ {
+ m_CameraSelector->setCurrentIndex(theNumItems - 1);
+ HandleCameraChanged(theNumItems - 1); // set to the last one
+ } else {
+ int theIndex;
+ if (thePreferredView < theNumItems - 2)
+ theIndex = thePreferredView;
+ else // possibly from old content where cameras are removed
+ theIndex = 0;
+ m_CameraSelector->setCurrentIndex(theIndex);
+ HandleCameraChanged(theIndex);
+ }
+}
+
+//==============================================================================
+/**
+ * Callback method when the camera is changed from the camera selection combo box
+ */
+void CEditCameraBar::OnCameraChanged()
+{
+ HandleCameraChanged(m_CameraSelector->currentIndex());
+}
+
+//==============================================================================
+/**
+ * Handle the switching of the current edit camera
+ * @param inIndex the index of the to-be-activated camera in the combo box
+ */
+void CEditCameraBar::HandleCameraChanged(int inIndex)
+{
+ Q3DStudio::IStudioRenderer &theRenderer = g_StudioApp.GetRenderer();
+ QStringList theCameraNames;
+ theRenderer.GetEditCameraList(theCameraNames);
+ int theNumCameras = theCameraNames.size();
+ if (inIndex < theNumCameras) {
+ theRenderer.SetEditCamera(inIndex);
+ m_ActiveCameraIndex = inIndex;
+ if (m_SceneView)
+ m_SceneView->SetViewMode(CPlayerContainerWnd::VIEW_EDIT);
+ } else if (inIndex > theNumCameras) {
+ theRenderer.SetEditCamera(-1);
+ m_ActiveCameraIndex = inIndex;
+ if (m_SceneView)
+ m_SceneView->SetViewMode(CPlayerContainerWnd::VIEW_SCENE);
+ } else {
+ m_CameraSelector->setCurrentIndex(m_ActiveCameraIndex);
+ }
+ if (m_SceneView)
+ m_SceneView->OnEditCameraChanged();
+
+ CMainFrame *theMainFrame = g_StudioApp.m_pMainWnd;
+ ASSERT(theMainFrame != nullptr);
+
+ // if the current tool is camera rotate and has been switch to 2d camera
+ // set the tool to camera pan
+ if (theMainFrame != nullptr) {
+ long theToolMode = g_StudioApp.GetToolMode();
+ if (theRenderer.DoesEditCameraSupportRotation(theRenderer.GetEditCamera()) == false
+ && theToolMode == STUDIO_TOOLMODE_CAMERA_ROTATE) {
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ m_SceneView->SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ }
+
+ // Trigger for tool changed. Changing between deployment/edit camera can change the tool
+ theMainFrame->OnUpdateToolChange();
+ }
+}
+
+//==============================================================================
+/**
+ * Set the current scene view. This scene view is notified when there is a camera
+ * changed.
+ * @param inSceneView the scene view object
+ */
+void CEditCameraBar::SetSceneView(CSceneView *inSceneView)
+{
+ m_SceneView = inSceneView;
+}
+
+//==============================================================================
+/**
+ * Enable/Disable the edit camera selector combo box.
+ * @param inFlag true to enable the camera selector combo box, false to disable
+ */
+void CEditCameraBar::Enable(bool inFlag)
+{
+ m_CameraSelector->setEnabled(inFlag);
+}
+
+//==============================================================================
+/**
+ * When the active camera is changed, the display string needs to be changed. Hence
+ * find which entry is the one which is modified and update with the new string
+ * @param inCamera the camera that has been modified
+ */
+void CEditCameraBar::OnEditCameraChanged()
+{
+ using qt3ds::QT3DSI32;
+ QT3DSI32 cameraIndex = g_StudioApp.GetRenderer().GetEditCamera();
+ long theNumEntry = m_CameraSelector->count();
+ for (long theIndex = 0; theIndex < theNumEntry; ++theIndex) {
+ if (m_CameraSelector->itemData(theIndex).toInt() == cameraIndex) {
+ if (theIndex != m_CameraSelector->currentIndex()) {
+ m_CameraSelector->setCurrentIndex(theIndex);
+ HandleCameraChanged(theIndex);
+ }
+ break;
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * Callback while creating the toolbar in MainFrm. This allows the toolbar to add
+ * other controls to it. For this toolbar, we want to add a descriptor and a camera
+ * selector dropdown combobox.
+ */
+//==============================================================================
+void CEditCameraBar::OnCustomizeToolbar()
+{
+ // Create the combo box
+ addWidget(m_CameraSelector = new QComboBox);
+ // We need to specify accessibleName and objectName for the combobox, as it's in the toolbar,
+ // and we want to use a different style for it.
+ m_CameraSelector->setAccessibleName(QStringLiteral("cameraSelector"));
+ m_CameraSelector->setObjectName(QStringLiteral("cameraSelector"));
+ m_CameraSelector->setMinimumWidth(145);
+}
diff --git a/src/Authoring/Studio/_Win/UI/EditCameraBar.h b/src/Authoring/Studio/_Win/UI/EditCameraBar.h
new file mode 100644
index 00000000..bd8427f5
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/EditCameraBar.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_EDIT_CAMERA_BAR
+#define INCLUDED_EDIT_CAMERA_BAR 1
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DispatchListeners.h"
+#include <vector>
+
+#include <QToolBar>
+
+QT_BEGIN_NAMESPACE
+class QComboBox;
+class QLabel;
+QT_END_NAMESPACE
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CSceneView;
+
+//==============================================================================
+/**
+ * @class CEditCameraBar
+ */
+class CEditCameraBar : public QToolBar, public CEditCameraChangeListener
+{
+ Q_OBJECT
+public:
+ CEditCameraBar(QWidget* parent = nullptr); // standard constructor
+ virtual ~CEditCameraBar();
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CEditCameraBar)
+ //}}AFX_VIRTUAL
+
+ // Implementation
+ // Generated message map functions
+ void OnCameraChanged();
+ void OnCustomizeToolbar();
+
+public:
+ void SetupCameras();
+ void SetSceneView(CSceneView *inSceneView);
+ void Enable(bool inFlag);
+ void HandleCameraChanged(int inIndex);
+
+ // CEditCameraChangeListener
+ void OnEditCameraChanged() override;
+ void OnEditCamerasTransformed() override {} // I am not interested in this
+ void OnAuthorZoomChanged() override {}
+
+protected:
+ CSceneView *m_SceneView; ///< The scene view object
+ long m_ActiveCameraIndex; ///< The index of the active camera in the list
+
+ // UI Controls definition
+ QLabel* m_CameraText; ///< Static text showing the word "Camera"
+ QComboBox* m_CameraSelector; ///< Combo box for selecting edit camera
+};
+
+#endif
diff --git a/src/Authoring/Studio/_Win/UI/EditorPane.cpp b/src/Authoring/Studio/_Win/UI/EditorPane.cpp
new file mode 100644
index 00000000..ef274392
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/EditorPane.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "EditorPane.h"
+
+//==============================================================================
+/**
+ * Constructor: Creates a CEditorPane
+ */
+CEditorPane::CEditorPane()
+ : m_EditObject(nullptr)
+{
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the CEditorPane
+ */
+CEditorPane::~CEditorPane()
+{
+}
+
+//==============================================================================
+/**
+ * Set the object that this window will edit.
+ * Recieve and keep the CAsset to be edited. You can override this method
+ * for each specific editor view class.
+ * @param inEditObject The CAsset to be represented and edited in this view.
+ */
+void CEditorPane::SetEditObject(CAsset *inEditObject)
+{
+ // Retain this object
+ m_EditObject = inEditObject;
+}
+
+//==============================================================================
+/**
+ * Get the object that this window is editing.
+ * return The CAsset that is associated with this window
+ */
+CAsset *CEditorPane::GetEditObject()
+{
+ // Return the asset
+ return m_EditObject;
+}
+
+//==============================================================================
+/**
+ * CloseEditor: Close the editor.
+ * Override to close each individual editor.
+ * @return false
+ */
+bool CEditorPane::CloseEditor()
+{
+ return false;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/UI/EditorPane.h b/src/Authoring/Studio/_Win/UI/EditorPane.h
new file mode 100644
index 00000000..9bc91694
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/EditorPane.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_EDITOR_PANE
+#define INCLUDED_EDITOR_PANE 1
+
+#pragma once
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CAsset;
+
+//==============================================================================
+/**
+ * @class CEditorPane
+ * @brief Abstract base class for various editor views.
+ *
+ * A base class for universally accessing information from editor views.
+ */
+class CEditorPane
+{
+ // Fields
+protected:
+ CAsset *m_EditObject; ///< object being edited by this window.
+
+ // Methods
+public:
+ CEditorPane();
+ virtual ~CEditorPane();
+ virtual void SetEditObject(CAsset *inEditObject);
+ CAsset *GetEditObject();
+ virtual bool CloseEditor();
+};
+
+#endif // INCLUDED_EDITOR_PANE \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/UI/FileDialogEX.cpp b/src/Authoring/Studio/_Win/UI/FileDialogEX.cpp
new file mode 100644
index 00000000..9183e536
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/FileDialogEX.cpp
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "Strings.h"
+#include <afxpriv.h>
+#include "FileDialogEX.h"
+#include "resource.h"
+#include "windowsx.h"
+#include "Userenv.h"
+#include "Commdlg.h"
+#include "CdErr.h"
+#include "Preferences.h"
+
+static const long SFILELISTBUFFERSIZE =
+ 2048; // Size of the char buffer used to store selected filenames
+// static BOOL IsWin2000();
+
+/////////////////////////////////////////////////////////////////////////////
+// CFileDialogEx
+
+IMPLEMENT_DYNAMIC(CFileDialogEx, CFileDialog)
+
+//==============================================================================
+/**
+ * CFileDialogEx: constructor
+ */
+//==============================================================================
+CFileDialogEx::CFileDialogEx(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
+ DWORD dwFlags, LPCTSTR lpszFilter, CWnd *pParentWnd)
+ : CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd)
+ , m_IsSaving(FALSE)
+ , m_LastFilterIndex(1)
+ , m_FileListBuffer(nullptr)
+ , m_WasCreateNewDirectoryChecked(false)
+ , m_CreateDirectoryCheckboxEnabled(false)
+ , m_Preferences(CPreferences::GetUserPreferences())
+{
+ m_IsSaving = !bOpenFileDialog; // if not openfiledlg, is saving
+ m_FilterIndex = 0; // init to 0; index starts from 1
+ m_ofnEx.pvReserved = nullptr;
+ m_ofnEx.dwReserved = 0;
+ m_ofnEx.FlagsEx = 0;
+
+ if (dwFlags & OFN_ALLOWMULTISELECT) {
+ // Create buffer for multiple selection
+ m_FileListBuffer = new TCHAR[SFILELISTBUFFERSIZE];
+ m_FileListBuffer[0] = '\0';
+
+ GetOFN().lpstrFile = m_FileListBuffer;
+ GetOFN().nMaxFile = SFILELISTBUFFERSIZE;
+ }
+}
+
+CFileDialogEx::~CFileDialogEx()
+{
+ if (m_FileListBuffer) {
+ delete[] m_FileListBuffer;
+ }
+}
+
+BEGIN_MESSAGE_MAP(CFileDialogEx, CFileDialog)
+//{{AFX_MSG_MAP(CFileDialogEX)
+ON_COMMAND(IDC_CHECK1, OnCreateNewDirectory)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * IsWin2000: function to determine if we are on win2k
+ *
+ * @return true if we are on win2k
+ */
+//==============================================================================
+// BOOL IsWin2000 ()
+//{
+// OSVERSIONINFOEX theOsvi;
+// BOOL OsVersionInfoEx;
+//
+// // Try calling GetVersionEx using the OSVERSIONINFOEX structure,
+// // which is supported on Windows 2000.
+// //
+// // If that fails, try using the OSVERSIONINFO structure.
+//
+// ZeroMemory( &theOsvi, sizeof( OSVERSIONINFOEX ) );
+// theOsvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
+// OsVersionInfoEx = GetVersionEx ( ( OSVERSIONINFO* ) &theOsvi );
+//
+// if( !OsVersionInfoEx )
+// {
+// // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
+//
+// theOsvi.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO );
+// if ( !GetVersionEx( ( OSVERSIONINFO* ) &theOsvi) )
+// return FALSE;
+// }
+//
+// switch ( theOsvi.dwPlatformId )
+// {
+// case VER_PLATFORM_WIN32_NT:
+//
+// if ( theOsvi.dwMajorVersion >= 5 )
+// return TRUE;
+//
+// break;
+// }
+// return FALSE;
+//}
+
+void CFileDialogEx::EnableCreateDirectoryCheckbox()
+{
+ m_CreateDirectoryCheckboxEnabled = true;
+}
+
+// http://msdn.microsoft.com/en-us/magazine/cc300434.aspx
+struct RegKeyOverrider
+{
+ const char *getRegKeyName()
+ {
+ return "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\ComDlg32\\PlacesBar";
+ }
+ HKEY m_TempKey;
+
+ RegKeyOverrider()
+ {
+ memset(&m_TempKey, 0, sizeof(HKEY));
+ long newKeyResult =
+ RegCreateKeyEx(HKEY_CURRENT_USER, L"UIComposer_FileDialog", 0, nullptr,
+ REG_OPTION_VOLATILE, KEY_ALL_ACCESS, nullptr, &m_TempKey, nullptr);
+ if (newKeyResult == ERROR_SUCCESS) {
+ long overrideResult = RegOverridePredefKey(HKEY_CURRENT_USER, m_TempKey);
+ ASSERT(overrideResult == ERROR_SUCCESS);
+ if (overrideResult == ERROR_SUCCESS) {
+ // Customize the places bar now in or overridden key.
+ HKEY placesKey;
+ long placesResult =
+ RegCreateKeyEx(HKEY_CURRENT_USER, CString(getRegKeyName()), 0, nullptr,
+ REG_OPTION_VOLATILE, KEY_ALL_ACCESS, nullptr, &placesKey, nullptr);
+ if (placesResult == ERROR_SUCCESS) {
+ TCHAR szHomeDirBuf[MAX_PATH] = { 0 };
+
+ HANDLE hToken = 0;
+ OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
+
+ DWORD BufSize = MAX_PATH;
+ GetUserProfileDirectory(hToken, szHomeDirBuf, &BufSize);
+
+ CloseHandle(hToken);
+
+ wcscat(szHomeDirBuf, L"\\Links");
+
+ size_t len = wcslen(szHomeDirBuf);
+ RegSetValueEx(placesKey, L"Place0", 0, REG_SZ, (const BYTE *)szHomeDirBuf,
+ (DWORD)len);
+
+ TCHAR buffer[32] = { 0 };
+ DWORD folderIds[] = { 8, 0, 17, 18 };
+
+ for (int idx = 0; idx < 4; ++idx) {
+ swprintf_s(buffer, L"Place%d", idx + 1);
+ long setKeyResult =
+ RegSetValueEx(placesKey, buffer, 0, REG_DWORD,
+ (const BYTE *)(folderIds + idx), sizeof(DWORD));
+ ASSERT(setKeyResult == ERROR_SUCCESS);
+ }
+ }
+ RegCloseKey(placesKey);
+ }
+ }
+ }
+ ~RegKeyOverrider()
+ {
+ RegOverridePredefKey(HKEY_CURRENT_USER, nullptr);
+ RegDeleteKey(m_TempKey, nullptr);
+ RegCloseKey(m_TempKey);
+ }
+};
+struct SErrorMap
+{
+ DWORD m_Error;
+ const char *m_Name;
+};
+static SErrorMap g_ErrorMap[] = {
+#define MAKE_STRUCT(name) { name, #name },
+ MAKE_STRUCT(CDERR_DIALOGFAILURE) MAKE_STRUCT(CDERR_FINDRESFAILURE)
+ MAKE_STRUCT(CDERR_INITIALIZATION) MAKE_STRUCT(CDERR_LOADRESFAILURE)
+ MAKE_STRUCT(CDERR_LOADSTRFAILURE) MAKE_STRUCT(CDERR_LOCKRESFAILURE)
+ MAKE_STRUCT(CDERR_MEMALLOCFAILURE) MAKE_STRUCT(CDERR_MEMLOCKFAILURE)
+ MAKE_STRUCT(CDERR_NOHINSTANCE) MAKE_STRUCT(CDERR_NOHOOK)
+ MAKE_STRUCT(CDERR_NOTEMPLATE) MAKE_STRUCT(CDERR_STRUCTSIZE)
+ MAKE_STRUCT(FNERR_BUFFERTOOSMALL) MAKE_STRUCT(FNERR_INVALIDFILENAME)
+ MAKE_STRUCT(FNERR_SUBCLASSFAILURE)
+#undef MAKE_STRUCT
+ { 0, nullptr },
+};
+//==============================================================================
+/**
+ * IsWin2000: Overloaded CFileDialog Function
+ *
+ * adds extra parameter if the operating system is win2k
+ *
+ * @return true for file open... false for file save as
+ */
+//==============================================================================
+INT_PTR CFileDialogEx::DoModal()
+{
+ ASSERT_VALID(this);
+ ASSERT(m_ofn.Flags & OFN_ENABLEHOOK);
+ ASSERT(m_ofn.lpfnHook != nullptr); // can still be a user hook
+
+ // zero out the file buffer for consistent parsing later
+ ASSERT(AfxIsValidAddress(m_ofn.lpstrFile, m_ofn.nMaxFile));
+ DWORD nOffset = (DWORD)_tcslen(m_ofn.lpstrFile) + 1;
+ ASSERT(nOffset <= m_ofn.nMaxFile);
+ memset(m_ofn.lpstrFile + nOffset, 0, (m_ofn.nMaxFile - nOffset) * sizeof(TCHAR));
+
+ if (!m_InitialDir.IsEmpty())
+ m_ofn.lpstrInitialDir = m_InitialDir;
+
+ // If the title has been specified, change it from the OS default
+ if (!m_Title.IsEmpty())
+ m_ofn.lpstrTitle = m_Title;
+
+ // If filterIndex has been changed, use it instead of the default
+ if (m_FilterIndex != 0)
+ m_ofn.nFilterIndex = m_FilterIndex;
+
+ if (m_CreateDirectoryCheckboxEnabled) {
+ // Begin customization for the checkbox for new project dialog
+ m_ofn.hInstance = GetModuleHandle(nullptr);
+ m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_NEWPROJEXT);
+ m_ofn.Flags |= OFN_ENABLETEMPLATE;
+ }
+
+ // WINBUG: This is a special case for the file open/save dialog,
+ // which sometimes pumps while it is coming up but before it has
+ // disabled the main window.
+ HWND hWndFocus = ::GetFocus();
+ BOOL bEnableParent = FALSE;
+
+ // OVerride the places bar so that is always shows favorites.
+ RegKeyOverrider regOverrider;
+ m_ofn.hwndOwner = PreModal();
+ AfxUnhookWindowCreate();
+ if (m_ofn.hwndOwner != nullptr && ::IsWindowEnabled(m_ofn.hwndOwner)) {
+ bEnableParent = TRUE;
+ ::EnableWindow(m_ofn.hwndOwner, FALSE);
+ }
+
+ _AFX_THREAD_STATE *pThreadState = AfxGetThreadState();
+ ASSERT(pThreadState->m_pAlternateWndInit == nullptr);
+
+ if (m_ofn.Flags & OFN_EXPLORER)
+ pThreadState->m_pAlternateWndInit = this;
+ else
+ AfxHookWindowCreate(this);
+
+ // This is whre is differs for 2000
+ ::memset(&m_ofnEx, 0, sizeof(m_ofnEx));
+ ::memcpy(&m_ofnEx, &m_ofn, sizeof(m_ofn));
+ // if ( IsWin2000() ){
+ // m_ofnEx.lStructSize = sizeof( m_ofnEx );
+ //}
+
+ int nResult;
+ if (m_bOpenFileDialog)
+ nResult = ::GetOpenFileName(&m_ofnEx);
+ else
+ nResult = ::GetSaveFileName(&m_ofnEx);
+
+ if (nResult == 0) {
+ DWORD error = ::CommDlgExtendedError();
+ if (error) {
+ SErrorMap *theError = nullptr;
+ for (theError = g_ErrorMap; theError->m_Name; ++theError) {
+ if (theError->m_Error == error) {
+ OutputDebugStringA("Massive failure in FileDialogEX!!\n");
+ OutputDebugStringA(theError->m_Name);
+ ASSERT(false);
+ }
+ }
+ }
+ }
+
+ // Copy back m_ofnEx -> m_ofn
+ ::memcpy(&m_ofn, &m_ofnEx, sizeof(m_ofn));
+ m_ofn.lStructSize = sizeof(m_ofn);
+
+ if (nResult)
+ ASSERT(pThreadState->m_pAlternateWndInit == nullptr);
+ pThreadState->m_pAlternateWndInit = nullptr;
+
+ // WINBUG: Second part of special case for file open/save dialog.
+ if (bEnableParent)
+ ::EnableWindow(m_ofn.hwndOwner, TRUE);
+ if (::IsWindow(hWndFocus))
+ ::SetFocus(hWndFocus);
+
+ PostModal();
+
+ if (nResult) {
+ m_LastFilterIndex = GetOFN().nFilterIndex;
+ }
+
+ return nResult ? nResult : IDCANCEL;
+}
+
+BOOL CFileDialogEx::OnFileNameOK()
+{
+ CFileStatus theFileStatus;
+ CString theFilePath = Q3DStudio::CString(GetOFN().lpstrFile);
+ // CString theFilePath = this->GetPathName(); // Somehow, this does not return the filename
+ // with extension
+ BOOL theReturnValue = FALSE;
+
+ if (m_IsSaving && CFile::GetStatus(theFilePath, theFileStatus)) {
+ if (theFileStatus.m_attribute & CFile::readOnly) {
+ Q3DStudio::CString theMsgTitle;
+ Q3DStudio::CString theMsg;
+ Q3DStudio::CString theFormattedText;
+ Q3DStudio::CString theFileNameText = GetOFN().lpstrFileTitle;
+ // Q3DStudio::CString theFileNameText = GetFileName( );
+
+ theMsgTitle = ::LoadResourceString(IDS_PROJNAME);
+ theMsg = ::LoadResourceString(IDS_SAVE_READONLY_WARNING);
+ theFormattedText.Format(theMsg, static_cast<const wchar_t *>(theFileNameText));
+
+ ::MessageBox(this->GetSafeHwnd(), theFormattedText, theMsgTitle,
+ MB_OK | MB_ICONEXCLAMATION);
+ theReturnValue = TRUE;
+ }
+ }
+
+ return theReturnValue;
+}
+
+void CFileDialogEx::SetInitialDirectory(const Q3DStudio::CString &inDir)
+{
+ Q3DStudio::CFilePath thePath(inDir);
+ if (thePath.IsFile())
+ thePath = thePath.GetDirectory();
+ m_InitialDir = thePath;
+}
+
+void CFileDialogEx::OnCreateNewDirectory()
+{
+ m_WasCreateNewDirectoryChecked = !m_WasCreateNewDirectoryChecked;
+ m_Preferences.SetValue("CreateDirForProject", m_WasCreateNewDirectoryChecked);
+}
+
+//=============================================================================
+/**
+ * Allows the user to set the title of the dialog. By default, the title is
+ * determined by the first parameter of the constructor (bOpenFileDialog).
+ * TRUE specifies a file open dialog and FALSE specifies a Save As dialog.
+ * The title of the window is then generated by the OS. This function enables
+ * you to set the title to any string you want, overriding the OS value.
+ * @param inTitle new title for this dialog; if an empty string is specified,
+ * the OS generated title will be displayed.
+ */
+void CFileDialogEx::SetWindowTitle(const Q3DStudio::CString &inTitle)
+{
+ m_Title = inTitle;
+}
+
+//=============================================================================
+/**
+ * Sets the filter to be selected when the dialog is opened, if specified.
+ * The filter is indexed from 1 to n.
+ *
+ * @param inFilterIndex the index of the filter to be applied as the default
+ * extension to be used when displaying the dialog.
+ * @author AT May 29 2003
+ */
+void CFileDialogEx::SetFilterIndex(const LONG inFilterIndex)
+{
+ m_FilterIndex = inFilterIndex;
+}
+
+BOOL CFileDialogEx::OnInitDialog()
+{
+ BOOL retval = CFileDialog::OnInitDialog();
+ if (m_CreateDirectoryCheckboxEnabled) {
+ CWnd *theWnd = GetDlgItem(IDC_CHECK1);
+ if (theWnd) {
+ m_WasCreateNewDirectoryChecked =
+ m_Preferences.GetValue("CreateDirForProject", true) ? 1 : 0;
+ Button_SetCheck(theWnd->GetSafeHwnd(), m_WasCreateNewDirectoryChecked ? 1 : 0);
+ }
+ }
+ return retval;
+}
+
+//=============================================================================
+/**
+ * Gets the filter index when the dialog is opened.
+ * The filter is indexed from 1 to n.
+ * The member was set at the end of DoModal.
+ *
+ * @return the filter index, starting from 1 to n
+ */
+long CFileDialogEx::GetLastFilterIndex()
+{
+ return m_LastFilterIndex;
+}
+
+//=============================================================================
+/**
+ * Retrieves the list of files selected during multiple selection
+ * @param outFileList vector to hold filenames
+ */
+void CFileDialogEx::RetrieveFileList(TFILELIST &outFileList) const
+{
+ outFileList.clear();
+ POSITION theStartPosition = GetStartPosition();
+
+ Q3DStudio::CString theFileName;
+ while (nullptr != theStartPosition) {
+ theFileName = GetNextPathName(theStartPosition);
+ outFileList.push_back(CUICFile(theFileName));
+ }
+}
diff --git a/src/Authoring/Studio/_Win/UI/FileDialogEX.h b/src/Authoring/Studio/_Win/UI/FileDialogEX.h
new file mode 100644
index 00000000..ad82de14
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/FileDialogEX.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#if !defined(AFX_FILEDIALOGEX_H__4CF114A7_E3C1_44AA_8A73_92CF2480D010__INCLUDED_)
+#define AFX_FILEDIALOGEX_H__4CF114A7_E3C1_44AA_8A73_92CF2480D010__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+struct OPENFILENAMEEX : public OPENFILENAME
+{
+ void *pvReserved;
+ DWORD dwReserved;
+ DWORD FlagsEx;
+};
+
+//==============================================================================
+/**
+ * CFileDialog: Extends the regular CFileDialog for win2k dialog box
+ */
+//==============================================================================
+class CFileDialogEx : public CFileDialog
+{
+ DECLARE_DYNAMIC(CFileDialogEx)
+
+public:
+ typedef std::vector<CUICFile> TFILELIST;
+ OPENFILENAMEEX m_ofnEx; ///< Extra structure passed in for win 2k dialog
+
+ //==========================================================================
+ // Methods
+ //==========================================================================
+ CFileDialogEx(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
+ LPCTSTR lpszDefExt = nullptr, LPCTSTR lpszFileName = nullptr,
+ DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = nullptr,
+ CWnd *pParentWnd = nullptr);
+
+ virtual ~CFileDialogEx();
+
+ void EnableCreateDirectoryCheckbox();
+ virtual void SetInitialDirectory(const Q3DStudio::CString &inDir);
+ virtual void SetWindowTitle(const Q3DStudio::CString &inTitle);
+ virtual void SetFilterIndex(const LONG inFilterIndex);
+ virtual BOOL OnInitDialog();
+ long GetLastFilterIndex();
+ void RetrieveFileList(TFILELIST &outFileList) const;
+
+ virtual INT_PTR DoModal();
+ virtual BOOL OnFileNameOK();
+ void IsSaving() { m_IsSaving = TRUE; }
+ bool WasCreateNewDirectoryChecked() { return m_WasCreateNewDirectoryChecked; }
+
+protected:
+ BOOL m_IsSaving;
+ Q3DStudio::CString m_InitialDir;
+ Q3DStudio::CString m_Title;
+ LONG m_FilterIndex;
+ long m_LastFilterIndex; //< the last filter index for when a file was selected
+ wchar_t *m_FileListBuffer;
+ bool m_CreateDirectoryCheckboxEnabled;
+ bool m_WasCreateNewDirectoryChecked;
+ // We have to cache a CPreferences here because we reroute the registry during
+ // doModal in order to make the file dialogue behavior differently.
+ // see RegKeyOverrider
+ CPreferences m_Preferences;
+
+ //==========================================================================
+ // Members
+ //==========================================================================
+
+ // Generated message map functions
+ //{{AFX_MSG(CFileDialogEx)
+ afx_msg void OnCreateNewDirectory();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_FILEDIALOGEX_H__4CF114A7_E3C1_44AA_8A73_92CF2480D010__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/GLVersionDlg.cpp b/src/Authoring/Studio/_Win/UI/GLVersionDlg.cpp
new file mode 100644
index 00000000..cb02578b
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/GLVersionDlg.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "GLVersionDlg.h"
+
+CGLVersionDlg::CGLVersionDlg(CWnd *pParent /*=nullptr*/)
+ : CDialog(CGLVersionDlg::IDD, pParent)
+{
+ m_Title = _T("");
+ m_Message = _T("");
+ m_Icon = nullptr;
+ m_DontShowAgain = FALSE;
+}
+
+CGLVersionDlg::~CGLVersionDlg()
+{
+}
+
+void CGLVersionDlg::DoDataExchange(CDataExchange *pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_GL_VERSION_ICON, m_WarningIcon);
+ DDX_Text(pDX, IDC_GL_VERSION_MESSAGE, m_Message);
+ DDX_Check(pDX, IDC_CHECK1, m_DontShowAgain);
+}
+
+BEGIN_MESSAGE_MAP(CGLVersionDlg, CDialog)
+END_MESSAGE_MAP()
+
+BOOL CGLVersionDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ // Set the title
+ this->SetWindowText(m_Title);
+
+ // Set icon
+ m_WarningIcon.SetIcon(::AfxGetApp()->LoadStandardIcon(m_Icon));
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CGLVersionDlg::Initialize(const Q3DStudio::CString &inTitle,
+ const Q3DStudio::CString &inMessage, bool inErrorIcon)
+{
+ // Set title and message
+ m_Title = CString(inTitle);
+ m_Message = CString(inMessage);
+
+ // Set which icon to load
+ if (inErrorIcon)
+ m_Icon = IDI_ERROR;
+ else
+ m_Icon = IDI_WARNING;
+}
+
+BOOL CGLVersionDlg::GetDontShowAgain()
+{
+ return m_DontShowAgain;
+}
diff --git a/src/Authoring/Studio/_Win/UI/GLVersionDlg.h b/src/Authoring/Studio/_Win/UI/GLVersionDlg.h
new file mode 100644
index 00000000..908a8441
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/GLVersionDlg.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_GL_VERSION_DLG
+#define INCLUDED_GL_VERSION_DLG 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "resource.h"
+
+//==============================================================================
+/**
+ * CGLVersionDlg: Dialog class for showing Open GL Version Warning
+ */
+//==============================================================================
+class CGLVersionDlg : public CDialog
+{
+public:
+ CGLVersionDlg(CWnd *pParent = nullptr); // standard constructor
+ virtual ~CGLVersionDlg();
+
+ // Dialog Data
+ enum { IDD = IDD_GL_VERSION_DLG };
+
+protected:
+ virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support
+
+ DECLARE_MESSAGE_MAP()
+ CStatic m_WarningIcon; // Warning icon
+ CString m_Title; // Title for the dialog
+ CString m_Message; // Warning message
+ BOOL m_DontShowAgain; // Set to true to "Don't show this dialog again"
+ LPCTSTR m_Icon; // Which icon to load
+
+public:
+ virtual BOOL OnInitDialog();
+ void Initialize(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inMessage,
+ bool inErrorIcon);
+ BOOL GetDontShowAgain();
+};
+
+#endif // INCLUDED_GL_VERSION_DLG
diff --git a/src/Authoring/Studio/_Win/UI/InterpolationDlg.cpp b/src/Authoring/Studio/_Win/UI/InterpolationDlg.cpp
new file mode 100644
index 00000000..57d6ae1d
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/InterpolationDlg.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix / Includes
+//==============================================================================
+
+#include "stdafx.h"
+#include "InterpolationDlg.h"
+#include "ui_InterpolationDlg.h"
+
+//==============================================================================
+/**
+ * Constructor: Creates a CInterpolationDlg.
+ *
+ * @param parent Pointer to the parent of this dialog (defaults to NULL)
+ */
+//==============================================================================
+CInterpolationDlg::CInterpolationDlg(QWidget *parent)
+ : QDialog(parent)
+ , m_ui(new Ui::InterpolationDlg)
+{
+ m_ui->setupUi(this);
+}
+
+CInterpolationDlg::~CInterpolationDlg()
+{
+ delete m_ui;
+ m_ui = nullptr;
+}
+
+void CInterpolationDlg::setEaseIn(uint value)
+{
+ m_ui->easeInSlider->setValue(value);
+}
+
+void CInterpolationDlg::setEaseOut(uint value)
+{
+ m_ui->easeOutSlider->setValue(value);
+}
+
+int CInterpolationDlg::easeIn() const
+{
+ return m_ui->easeInSlider->value();
+}
+
+int CInterpolationDlg::easeOut() const
+{
+ return m_ui->easeOutSlider->value();
+}
+
+
diff --git a/src/Authoring/Studio/_Win/UI/InterpolationDlg.h b/src/Authoring/Studio/_Win/UI/InterpolationDlg.h
new file mode 100644
index 00000000..5f371625
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/InterpolationDlg.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_INTERPOLATION_DLG
+#define INCLUDED_INTERPOLATION_DLG 1
+
+#pragma once
+
+#include <QDialog>
+
+namespace Ui {
+class InterpolationDlg;
+}
+
+//==============================================================================
+/**
+ * CInterpolationDlg: Dialog class for editing the ease-in/ease-out values of keyframes.
+ */
+//==============================================================================
+class CInterpolationDlg : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit CInterpolationDlg(QWidget *parent = nullptr); // standard constructor
+ ~CInterpolationDlg();
+
+ void setEaseIn(uint value);
+ void setEaseOut(uint value);
+ int easeIn() const;
+ int easeOut() const;
+
+protected:
+ Ui::InterpolationDlg* m_ui = nullptr;
+};
+
+#endif // INCLUDED_INTERPOLATION_DLG
diff --git a/src/Authoring/Studio/_Win/UI/InterpolationDlg.ui b/src/Authoring/Studio/_Win/UI/InterpolationDlg.ui
new file mode 100644
index 00000000..f0a0a759
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/InterpolationDlg.ui
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>InterpolationDlg</class>
+ <widget class="QDialog" name="InterpolationDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>425</width>
+ <height>195</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Set Keyframe Interpolation</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="1" colspan="2">
+ <widget class="QSlider" name="easeOutSlider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Ease In:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="label_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Smooth</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2">
+ <widget class="QSlider" name="easeInSlider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="label_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Linear</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="label_5">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Linear</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QLabel" name="label_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Smooth</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Ease Out:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QSpinBox" name="easeInSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QSpinBox" name="easeOutSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>InterpolationDlg</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>224</x>
+ <y>272</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>InterpolationDlg</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeInSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeInSpinBox</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>331</x>
+ <y>21</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>542</x>
+ <y>35</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeOutSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeOutSpinBox</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>210</x>
+ <y>93</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>545</x>
+ <y>93</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeInSpinBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeInSlider</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>533</x>
+ <y>24</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>408</x>
+ <y>18</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>easeOutSpinBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>easeOutSlider</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>546</x>
+ <y>98</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>338</x>
+ <y>84</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/Authoring/Studio/_Win/UI/MemoryDC.cpp b/src/Authoring/Studio/_Win/UI/MemoryDC.cpp
new file mode 100644
index 00000000..a253e89a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MemoryDC.cpp
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "resource.h"
+#include "MemoryDC.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CMemoryDC
+
+//==============================================================================
+/*
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CMemoryDC::CMemoryDC()
+ : m_ValidFlag(FALSE)
+ , m_SrcDC(nullptr)
+ , m_OldBmp(nullptr)
+{
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CMemoryDC::~CMemoryDC()
+{
+ // automatically release and draw on exit
+ Release();
+}
+
+//==============================================================================
+/**
+ * Create
+ *
+ * Creates the memory DC and image bitmap
+ *
+ * @param inDC Source device context
+ * @param inSrcRect CRect containing the source rectangle for drawing
+ */
+//==============================================================================
+void CMemoryDC::Create(CDC *inDC, CRect inSrcRect)
+{
+ ASSERT(inDC != nullptr);
+
+ if (!m_ValidFlag) {
+ // create the memory DC
+ CreateCompatibleDC(inDC);
+
+ // save the source DC
+ m_SrcDC = inDC;
+
+ // keep track of the destination rectangle
+ m_SrcRect.CopyRect(inSrcRect);
+
+ // create a bitmap for the memory bitmap image
+ m_MemBmp.CreateCompatibleBitmap(inDC, inSrcRect.Width(), inSrcRect.Height());
+
+ // select the memory image into the memory DC
+ m_OldBmp = SelectObject(&m_MemBmp);
+
+ m_ValidFlag = TRUE;
+ }
+}
+
+//==============================================================================
+/**
+ * Release
+ *
+ * Releases the memory DC and image bitmap and optionally copies the image
+ * to the source DC.
+ *
+ * @param inCopyToSourceFlag If TRUE, copies the memory image to the source DC
+ */
+//==============================================================================
+void CMemoryDC::Release(BOOL inCopyToSourceFlag)
+{
+ // copy the offscreen buffer to the sourceDC passed in Create()
+
+ if (m_ValidFlag) {
+ // blit to source DC to the m_SrcRect
+ if ((inCopyToSourceFlag) && (m_SrcDC != nullptr))
+ m_SrcDC->BitBlt(m_SrcRect.left, m_SrcRect.top, m_SrcRect.Width(), m_SrcRect.Height(),
+ this, 0, 0, SRCCOPY);
+
+ // de-select the memory image from the DC
+ SelectObject(m_OldBmp);
+
+ // delete the memory bitmap image
+ m_MemBmp.DeleteObject();
+
+ // delete the memory DC
+ DeleteDC();
+
+ m_ValidFlag = FALSE;
+ m_OldBmp = nullptr;
+ }
+}
+
+//==============================================================================
+/**
+ * CopySourceImage
+ *
+ * Copies the source image from the m_SrcRect into the memory DC/image.
+ *
+ * @param None
+ */
+//==============================================================================
+void CMemoryDC::CopySourceImage()
+{
+ if (m_ValidFlag) {
+ // copy the image from the source rectangle to the offscreen image
+ if (m_SrcDC != nullptr)
+ this->BitBlt(0, 0, m_SrcRect.Width(), m_SrcRect.Height(), m_SrcDC, m_SrcRect.left,
+ m_SrcRect.top, SRCCOPY);
+ }
+}
+
+//==============================================================================
+/**
+ * ConvertRect
+ *
+ * Converts a rectangle based on the source coordinates to one based on
+ * the memory image's coordinates.
+ *
+ * @param inDrawRect Source drawing CRect
+ *
+ * @return CRect Contains the converted rectangle
+ */
+//==============================================================================
+CRect CMemoryDC::ConvertRect(CRect inDrawRect)
+{
+ CRect theRect;
+
+ theRect.CopyRect(inDrawRect);
+ theRect.OffsetRect(-m_SrcRect.left, -m_SrcRect.top);
+
+ return theRect;
+}
+
+//==============================================================================
+/**
+ * ConvertPoint
+ *
+ * Converts a point based on the source coordinates to one based on
+ * the memory image's coordinates.
+ *
+ * @param inDrawRect Source drawing CPoint
+ *
+ * @return CPoint Contains the converted point
+ */
+//==============================================================================
+CPoint CMemoryDC::ConvertPoint(CPoint inDrawPoint)
+{
+ CPoint thePoint;
+
+ // convert point relative to this DC
+ thePoint = inDrawPoint;
+ thePoint.x -= m_SrcRect.left;
+ thePoint.y -= m_SrcRect.top;
+
+ return thePoint;
+}
+
+//==============================================================================
+/**
+ * ConvertXPos
+ *
+ * Converts an x-position based on the source coordinates to one based on
+ * the memory image's coordinates.
+ *
+ * @param inXValue Source drawing x-position
+ *
+ * @return long Contains the converted x-position
+ */
+//==============================================================================
+long CMemoryDC::ConvertXPos(long inXValue)
+{
+ long theXPos;
+
+ // convert x coordinate relative to this DC
+ theXPos = (long)inXValue - (long)m_SrcRect.left;
+
+ return theXPos;
+}
+
+//==============================================================================
+/**
+ * ConvertYPos
+ *
+ * Converts an y-position based on the source coordinates to one based on
+ * the memory image's coordinates.
+ *
+ * @param inYValue Source drawing y-position
+ *
+ * @return long Contains the converted y-position
+ */
+//==============================================================================
+long CMemoryDC::ConvertYPos(long inYValue)
+{
+ long theYPos;
+
+ // convert y coordinate relative to this DC
+ theYPos = (long)inYValue - (long)m_SrcRect.top;
+
+ return theYPos;
+}
+
+//==============================================================================
+/**
+ * SetRect
+ *
+ * Sets the drawing/output bounding rectangle.
+ *
+ * @param inRect Bounding rectangle for drawing
+ */
+//==============================================================================
+void CMemoryDC::SetRect(CRect inRect)
+{
+ m_SrcRect = inRect;
+}
diff --git a/src/Authoring/Studio/_Win/UI/MemoryDC.h b/src/Authoring/Studio/_Win/UI/MemoryDC.h
new file mode 100644
index 00000000..f72701e0
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MemoryDC.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_MEMORY_DC_H
+#define INCLUDED_MEMORY_DC_H
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+/**
+ * CMemoryDC: Subclassed CDC for drawing offscreen
+ *
+ * This is a subclassed CDC so we can control drawing into a DC with offscreen
+ * buffers to prevent flickering.
+ */
+//==============================================================================
+
+class CMemoryDC : public CDC
+{
+public:
+ //==========================================================================
+ // Fields
+ //==========================================================================
+
+protected:
+ BOOL m_ValidFlag; // TRUE if we can successfully release/copy the offscreen image to the screen
+ CRect m_SrcRect; // Bounding rectangle for drawing
+ CBitmap m_MemBmp; // Offscreen bitmap image
+ CBitmap *m_OldBmp; // Previous bitmap in the offscreen DC
+ CDC *m_SrcDC; // Source device context for final blit
+
+ //==========================================================================
+ // Methods
+ //==========================================================================
+
+public:
+ void SetRect(CRect inRect);
+
+ // Construction
+
+ CMemoryDC();
+ virtual ~CMemoryDC();
+
+ // Access
+
+ CPoint ConvertPoint(CPoint inDrawPoint);
+ CRect ConvertRect(CRect inDrawRect);
+ long ConvertXPos(long inXValue);
+ long ConvertYPos(long inYValue);
+ void CopySourceImage();
+ void Create(CDC *inDC, CRect inSrcRect);
+
+ void Release(BOOL inCopyToSourceFlag = TRUE);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // INCLUDED_MEMORY_DC_H
diff --git a/src/Authoring/Studio/_Win/UI/MenuEdit.cpp b/src/Authoring/Studio/_Win/UI/MenuEdit.cpp
new file mode 100644
index 00000000..39c82246
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MenuEdit.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "stdafx.h"
+#include "MenuEdit.h"
+#include "BCMenu.h"
+#include "StudioColors.h"
+
+//==============================================================================
+// Message Map
+//==============================================================================
+
+BEGIN_MESSAGE_MAP(CMenuEdit, CEdit)
+//{{AFX_MSG_MAP(CMenuEdit)
+ON_WM_SETFOCUS()
+ON_WM_CONTEXTMENU()
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+// IMPLEMENTATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Constructor: Creates a CMenuEdit
+ */
+//==============================================================================
+CMenuEdit::CMenuEdit()
+{
+}
+
+//==============================================================================
+/**
+ * OnSetFocus: The message handler for accepting focus.
+ *
+ * @param pOldWnd The window that had focus last.
+ */
+//==============================================================================
+void CMenuEdit::OnSetFocus(CWnd *pOldWnd)
+{
+ // Allow the parent to handle the request.
+ CEdit::OnSetFocus(pOldWnd);
+
+ // Select the entire text.
+ this->SetSel(0, -1);
+}
+
+//******************************************************************************
+// DYNAMIC CREATION
+//******************************************************************************
+
+IMPLEMENT_DYNAMIC(CMenuEdit, CEdit)
+
+//==============================================================================
+/**
+ * OnContextMenu: WM_CONTEXTMENU handler for the CMenuEdit.
+ *
+ * @param inWnd This window.
+ * @param inPoint Mouse position when the right button was clicked.
+ */
+//==============================================================================
+void CMenuEdit::OnContextMenu(CWnd *inWnd, CPoint inPoint)
+{
+ Q_UNUSED(inWnd);
+
+ // Added just because Justin has an eye for detail. :)
+
+ BCMenu theMenu;
+ BCMenu *thePopupMenu = nullptr;
+ long theMenuCmd;
+
+ if (GetFocus() != this)
+ this->SetFocus();
+
+ // Load the context menu
+ theMenu.LoadMenu(IDR_CONTEXT_EDIT);
+#ifdef _USECONTENTMENUIMAGES_
+ theMenu.SetBitmapBackground(MENU_IMAGELIST_BACKCOLOR);
+ theMenu.LoadToolbar(IDC_EDITCONTEXTTOOLBAR);
+#endif
+
+ thePopupMenu = (BCMenu *)theMenu.GetSubMenu(0);
+
+ // Enable/disable menu items
+ if (!this->CanUndo())
+ thePopupMenu->EnableMenuItem(IDC_UNDO, MF_BYCOMMAND | MF_GRAYED);
+
+ // Disable the Select All if there is no text in the control
+ if (this->GetWindowTextLength() == 0)
+ thePopupMenu->EnableMenuItem(IDC_SELECTALL, MF_BYCOMMAND | MF_GRAYED);
+
+ // Disable paste if there is no CF_TEXT on the clipboard
+ if (!IsClipboardFormatAvailable(CF_TEXT))
+ thePopupMenu->EnableMenuItem(IDC_PASTE, MF_BYCOMMAND | MF_GRAYED);
+
+ // Check if any text is selected
+ DWORD theSelection = this->GetSel();
+ if (LOWORD(theSelection) == HIWORD(theSelection)) {
+ // Disable cut, copy and delete commands if no text is selected
+ thePopupMenu->EnableMenuItem(IDC_CUT, MF_BYCOMMAND | MF_GRAYED);
+ thePopupMenu->EnableMenuItem(IDC_COPY, MF_BYCOMMAND | MF_GRAYED);
+ thePopupMenu->EnableMenuItem(IDC_DELETE, MF_BYCOMMAND | MF_GRAYED);
+ }
+
+ // Post the menu and handle the command here.
+ theMenuCmd = (long)thePopupMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD
+ | TPM_NONOTIFY,
+ inPoint.x, inPoint.y, this, nullptr);
+ switch (theMenuCmd) {
+ case IDC_UNDO:
+ this->Undo();
+ break;
+
+ case IDC_CUT:
+ this->Cut();
+ break;
+
+ case IDC_COPY:
+ this->Copy();
+ break;
+
+ case IDC_PASTE:
+ this->Paste();
+ break;
+
+ case IDC_DELETE:
+ // Delete the selected text
+ this->ReplaceSel(L"", FALSE);
+ break;
+
+ case IDC_SELECTALL:
+ // Select the entire text.
+ this->SetSel(0, -1);
+ break;
+ }
+
+ theMenu.DestroyMenu();
+}
diff --git a/src/Authoring/Studio/_Win/UI/MenuEdit.h b/src/Authoring/Studio/_Win/UI/MenuEdit.h
new file mode 100644
index 00000000..9aae97e2
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MenuEdit.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef _MENUEDIT_H_
+#define _MENUEDIT_H_
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+// Class
+//==============================================================================
+
+//==============================================================================
+/**
+ * @class CMenuEdit
+ * @brief This edit control has a BCMenu context menu.
+ */
+//==============================================================================
+class CMenuEdit : public CEdit
+{
+ // Fields
+
+public:
+ // Methods
+
+public:
+ DECLARE_DYNAMIC(CMenuEdit)
+ CMenuEdit();
+ virtual ~CMenuEdit() {}
+
+protected:
+ //{{AFX_MSG(CMenuEdit)
+ afx_msg void OnSetFocus(CWnd *pOldWnd);
+ afx_msg void OnContextMenu(CWnd *pWnd, CPoint point);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif // _MENUEDIT_H_
diff --git a/src/Authoring/Studio/_Win/UI/MenuItem.cpp b/src/Authoring/Studio/_Win/UI/MenuItem.cpp
new file mode 100644
index 00000000..beb77d98
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MenuItem.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "MenuItem.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+//==============================================================================
+/**
+ * CMenuItem: constructor
+ *
+ * @param inName name of the file
+ * @param inPath path to the file
+ * @param inID ID tag for this handler in the menu
+ */
+//==============================================================================
+CMenuItem::CMenuItem(CString inName, CString inPath, UINT inID)
+{
+ m_Name = inName;
+ m_ID = inID;
+ m_Path = inPath;
+}
+
+CMenuItem::~CMenuItem()
+{
+}
diff --git a/src/Authoring/Studio/_Win/UI/MenuItem.h b/src/Authoring/Studio/_Win/UI/MenuItem.h
new file mode 100644
index 00000000..f8033b81
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/MenuItem.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#if !defined(AFX_MENUITEM_H__6383095D_C084_44EB_A6D0_04CC1DA1B74F__INCLUDED_)
+#define AFX_MENUITEM_H__6383095D_C084_44EB_A6D0_04CC1DA1B74F__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// CMenuItem Class
+//==============================================================================
+
+//==============================================================================
+/**
+ * CMenuItem: Object for creating dynamic menus
+ */
+//==============================================================================
+class CMenuItem : public CObject
+{
+public:
+ CMenuItem(CString inName, CString inPath, UINT inID);
+ virtual ~CMenuItem();
+ UINT GetID() { return m_ID; };
+ CString GetPath() { return m_Path; };
+ CString GetName() { return m_Name; };
+protected:
+ CString m_Path; ///< Path to the file
+ CString m_Name; ///< Name to use in the menu
+ UINT m_ID; ///< ID of this menu item
+};
+
+#endif // !defined(AFX_MENUITEM_H__6383095D_C084_44EB_A6D0_04CC1DA1B74F__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/NumericEdit.cpp b/src/Authoring/Studio/_Win/UI/NumericEdit.cpp
new file mode 100644
index 00000000..73ff7bc8
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/NumericEdit.cpp
@@ -0,0 +1,347 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "NumericEdit.h"
+
+#include <minmax.h>
+
+/////////////////////////////////////////////////////////////////////////////
+// CNumericEdit class
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CNumericEdit::CNumericEdit()
+{
+ m_RangeLow = -1;
+ m_RangeHigh = -1;
+
+ m_WrapFlag = FALSE;
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CNumericEdit::~CNumericEdit()
+{
+}
+
+//=============================================================================
+/**
+ * Message Map
+ */
+//=============================================================================
+BEGIN_MESSAGE_MAP(CNumericEdit, CEdit)
+//{{AFX_MSG_MAP(CNumericEdit)
+ON_CONTROL_REFLECT(EN_KILLFOCUS, OnKillFocus)
+ON_CONTROL_REFLECT(EN_UPDATE, OnUpdate)
+ON_WM_CHAR()
+ON_WM_MOUSEWHEEL()
+ON_WM_KEYDOWN()
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//=============================================================================
+/**
+ * SetRange: Sets the value range for this control.
+ *
+ * @param inRangeLow Low range.
+ * @param inRangeHigh High range
+ */
+//=============================================================================
+void CNumericEdit::SetRange(long inRangeLow, long inRangeHigh)
+{
+ // Ensure they are in low/high order
+ m_RangeLow = min(inRangeLow, inRangeHigh);
+ m_RangeHigh = max(inRangeLow, inRangeHigh);
+}
+
+//=============================================================================
+/**
+ * SetValue: Sets the numeric value for this control.
+ *
+ * @param inValue The new value for this control.
+ */
+//=============================================================================
+void CNumericEdit::SetValue(long inValue)
+{
+ CString theStrValue;
+
+ theStrValue.Format(L"%lu", inValue);
+ this->SetWindowText(theStrValue);
+}
+
+//=============================================================================
+/**
+ * GetValue: Returns the numeric value for this control.
+ *
+ * @param None
+ *
+ * @return long The numeric value for this control.
+ */
+//=============================================================================
+long CNumericEdit::GetValue()
+{
+ CString theStrValue;
+
+ // Get the current control value.
+ this->GetWindowText(theStrValue);
+
+ // Convert to long and return.
+ return atol((char *)LPCTSTR(theStrValue));
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CNumericEdit message handlers
+
+//=============================================================================
+/**
+ * OnKillFocus: Handle the EN_KILLFOCUS and validate data.
+ *
+ * @param None
+ */
+//=============================================================================
+void CNumericEdit::OnKillFocus()
+{
+ this->ValidateData();
+}
+
+//=============================================================================
+/**
+ * OnUpdate: Handle the EN_UPDATE and handle validation before the control is updated.
+ *
+ * @param None
+ */
+//=============================================================================
+void CNumericEdit::OnUpdate()
+{
+ // TODO: If this is a RICHEDIT control, the control will not
+ // send this notification unless you override the CEdit::OnInitDialog()
+ // function to send the EM_SETEVENTMASK message to the control
+ // with the ENM_UPDATE flag ORed into the lParam mask.
+
+ // TODO: Add your control notification handler code here
+
+ this->ValidateData();
+}
+
+//=============================================================================
+/**
+ * OnChar: Handle the WM_CHAR and validate the key that was pressed.
+ *
+ * @param inChar
+ * @param inRepCnt
+ * @param inFlags
+ */
+//=============================================================================
+void CNumericEdit::OnChar(UINT inChar, UINT inRepCnt, UINT inFlags)
+{
+ if (IsNumeric(inChar) || IsEditKey(inChar)) {
+ CEdit::OnChar(inChar, inRepCnt, inFlags);
+ }
+}
+
+//=============================================================================
+/**
+ * OnKeyDown: Handle the WM_KEYDOWN and validate the key that was pressed.
+ *
+ * @param inChar
+ * @param inRepCnt
+ * @param inFlags
+ */
+//=============================================================================
+void CNumericEdit::OnKeyDown(UINT inChar, UINT inRepCnt, UINT inFlags)
+{
+ if (inChar == VK_UP) {
+ this->IncrementValue(+1);
+ this->SetSel(0, -1);
+ } else if (inChar == VK_DOWN) {
+ this->IncrementValue(-1);
+ this->SetSel(0, -1);
+ } else {
+ CEdit::OnKeyDown(inChar, inRepCnt, inFlags);
+ }
+}
+
+//=============================================================================
+/**
+ * IsEditKey: Determine if the pressed key was an edit key.
+ *
+ * @param inChar Key character value.
+ *
+ * @return TRUE if an editing key
+ */
+//=============================================================================
+BOOL CNumericEdit::IsEditKey(UINT inChar)
+{
+ BOOL theEditKeyFlag = FALSE;
+
+ if (inChar == VK_DELETE || inChar == VK_BACK || inChar == VK_LEFT || inChar == VK_RIGHT
+ || inChar == VK_HOME || inChar == VK_END || inChar == VK_UP || inChar == VK_DOWN)
+ theEditKeyFlag = TRUE;
+
+ return theEditKeyFlag;
+}
+
+//=============================================================================
+/**
+ * IsNumeric: Determine if the pressed key was a numeric key.
+ *
+ * @param inChar Key character value.
+ *
+ * @return TRUE if a numeric key
+ */
+//=============================================================================
+BOOL CNumericEdit::IsNumeric(UINT inChar)
+{
+ CString theNumericCheck = L"0123456789";
+ BOOL theNumericFlag = FALSE;
+
+ // Determine if the character is a numeric value.
+ if (theNumericCheck.Find((TCHAR)inChar) != -1) {
+ theNumericFlag = TRUE;
+ }
+
+ return theNumericFlag;
+}
+
+//=============================================================================
+/**
+ * ValidateData: Validates the value in the control to keep within range.
+ *
+ * @param None
+ */
+//=============================================================================
+void CNumericEdit::ValidateData()
+{
+ CString theStrValue;
+ long theValue = 0;
+ BOOL theChangeFlag = FALSE;
+
+ // Get the current text in the control.
+ this->GetWindowText(theStrValue);
+ if (theStrValue.GetLength() == 0) {
+ theValue = 0;
+ theChangeFlag = TRUE;
+ } else
+ // Check to see that a range has been set
+ if (m_RangeLow != -1 && m_RangeHigh != -1) {
+ theValue = this->GetValue();
+
+ // Check against the low and high range
+ if (theValue < m_RangeLow) {
+ theValue = m_RangeLow;
+ theChangeFlag = TRUE;
+ } else if (theValue > m_RangeHigh) {
+ theValue = m_RangeHigh;
+ theChangeFlag = TRUE;
+ }
+ }
+
+ // Has the value changed?
+ if (theChangeFlag) {
+ // Update the control's value.
+ this->SetValue(theValue);
+ this->SetSel(0, -1);
+ }
+}
+
+//=============================================================================
+/**
+ * IncrementValue: Increments the current value by inAmount
+ *
+ * @param inAmount Amount to change the current control value.
+ */
+//=============================================================================
+void CNumericEdit::IncrementValue(long inAmount)
+{
+ long theValue;
+
+ // Get the current value
+ theValue = this->GetValue();
+
+ // Change theValue
+ theValue += inAmount;
+
+ // Has a range been set?
+ if (m_RangeLow != -1 && m_RangeHigh != -1) {
+ if (theValue < m_RangeLow) {
+ theValue = m_RangeLow;
+
+ if (m_WrapFlag)
+ theValue = m_RangeHigh;
+ } else if (theValue > m_RangeHigh) {
+ theValue = m_RangeHigh;
+
+ if (m_WrapFlag)
+ theValue = m_RangeLow;
+ }
+ }
+
+ this->SetValue(theValue);
+}
+
+//=============================================================================
+/**
+ * OnMouseWheel: Handle the WM_MOUSEWHEEL message.
+ *
+ * @param inFlags
+ * @param inzDelta
+ * @param inPoint
+ *
+ * @return TRUE if processed.
+ */
+//=============================================================================
+BOOL CNumericEdit::OnMouseWheel(UINT inFlags, short inzDelta, CPoint inPoint)
+{
+ long theWheelDelta = 0;
+
+ if (inzDelta != 0)
+ theWheelDelta = inzDelta / abs(inzDelta);
+
+ this->IncrementValue(theWheelDelta);
+
+ this->SetSel(0, -1);
+
+ return CEdit::OnMouseWheel(inFlags, inzDelta, inPoint);
+}
diff --git a/src/Authoring/Studio/_Win/UI/NumericEdit.h b/src/Authoring/Studio/_Win/UI/NumericEdit.h
new file mode 100644
index 00000000..61a4017a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/NumericEdit.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#if !defined(AFX_NUMERICEDIT_H__F08CC602_8CD7_4A27_AC46_48A80A7D8FD0__INCLUDED_)
+#define AFX_NUMERICEDIT_H__F08CC602_8CD7_4A27_AC46_48A80A7D8FD0__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "MenuEdit.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CNumericEdit window
+
+class CNumericEdit : public CMenuEdit
+{
+ // Construction
+public:
+ CNumericEdit();
+
+ // Attributes
+public:
+ void SetAllowWrap(BOOL inWrapFlag) { m_WrapFlag = inWrapFlag; }
+
+protected:
+ long m_RangeLow, m_RangeHigh;
+ BOOL m_WrapFlag;
+
+ // Operations
+public:
+ long GetValue();
+
+ void SetRange(long inRangeLow, long inRangeHigh);
+ void SetValue(long inValue);
+
+protected:
+ void IncrementValue(long inAmount);
+ BOOL IsEditKey(UINT inChar);
+ BOOL IsNumeric(UINT inChar);
+
+ void ValidateData();
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CNumericEdit)
+ //}}AFX_VIRTUAL
+
+ // Implementation
+public:
+ virtual ~CNumericEdit();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CNumericEdit)
+ afx_msg void OnKillFocus();
+ afx_msg void OnUpdate();
+ afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_NUMERICEDIT_H__F08CC602_8CD7_4A27_AC46_48A80A7D8FD0__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.cpp b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.cpp
new file mode 100644
index 00000000..64d7e2f0
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.cpp
@@ -0,0 +1,510 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "UICOptions.h"
+#include "SceneView.h"
+#include "Doc.h"
+#include "StudioProjectSettings.h"
+#include "Dispatch.h"
+#include "HotKeys.h"
+#include "MasterP.h"
+#include "StudioApp.h"
+#include "IStudioRenderer.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "PlatformStrings.h"
+#include "PlayerContainerWnd.h"
+#include "UICDMStudioSystem.h"
+#include "Core.h"
+#include "MainFrm.h"
+#include "StudioUtils.h"
+
+#include <QtWidgets/qscrollbar.h>
+#include <QtGui/qevent.h>
+
+//==============================================================================
+// Class CPlayerContainerWnd
+//==============================================================================
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CPlayerContainerWnd::CPlayerContainerWnd(CSceneView *inSceneView)
+ : QAbstractScrollArea(inSceneView)
+ , m_SceneView(inSceneView)
+ , m_PlayerWnd(NULL)
+ , m_IsMouseDown(false)
+ , m_IsMiddleMouseDown(false)
+ , m_ViewMode(VIEW_SCENE)
+{
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CPlayerContainerWnd::~CPlayerContainerWnd()
+{
+}
+
+bool CPlayerContainerWnd::ShouldHideScrollBars()
+{
+ return m_ViewMode == VIEW_EDIT || g_StudioApp.IsAuthorZoom();
+}
+
+//==============================================================================
+/**
+ * SetPlayerWndPosition: Sets the position of the child player window
+ *
+ * Called when the view is scrolled to position the child player window
+ * @param outLeftPresentationEdge the left edge of the presentation, with the scroll position
+ *taken into consideration
+ * @param outTopPresentionEdge the top edge of the presentation, with the scroll
+ *position taken into consideration
+ *
+ */
+//==============================================================================
+void CPlayerContainerWnd::SetPlayerWndPosition(long &outLeftPresentationEdge,
+ long &outTopPresentionEdge)
+{
+ long theHScrollPosition, theVScrollPosition;
+ // Negate to adjust actual client positions
+ theHScrollPosition = -horizontalScrollBar()->value();
+ theVScrollPosition = -verticalScrollBar()->value();
+
+ QRect theClientRect = rect();
+
+ // Horizontal scrollbar does not exist
+ if (m_ClientRect.width() < theClientRect.width()) {
+ theHScrollPosition =
+ theClientRect.left() + (theClientRect.width() / 2) - (m_ClientRect.width() / 2);
+ outLeftPresentationEdge = theHScrollPosition;
+ } else // This stays a negated value
+ outLeftPresentationEdge = theHScrollPosition;
+
+ // Vertical scrollbar does not exist
+ if (m_ClientRect.height() < theClientRect.height()) {
+ theVScrollPosition =
+ theClientRect.top() + (theClientRect.height() / 2) - (m_ClientRect.height() / 2);
+ outTopPresentionEdge = theVScrollPosition;
+ } else // This stays a negated value
+ outTopPresentionEdge = theVScrollPosition;
+
+ // Move the child player window
+ m_PlayerWnd->setGeometry(QRect(QPoint(theHScrollPosition, theVScrollPosition), m_ClientRect.size()));
+}
+
+//==============================================================================
+/**
+ * SetScrollRanges: Sets the scroll ranges when the view is being resized
+ */
+//==============================================================================
+void CPlayerContainerWnd::SetScrollRanges()
+{
+
+ long theScrollWidth = 0;
+ long theScrollHeight = 0;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ if (ShouldHideScrollBars()) {
+ horizontalScrollBar()->setRange(0, 0);
+ verticalScrollBar()->setRange(0, 0);
+ horizontalScrollBar()->setValue(0);
+ verticalScrollBar()->setValue(0);
+ } else
+#endif
+ {
+ QSize theSize = GetEffectivePresentationSize();
+
+ theScrollWidth = theSize.width();
+ theScrollHeight = theSize.height();
+
+
+ // Set scrollbar ranges
+ horizontalScrollBar()->setRange(0, theScrollWidth - width());
+ verticalScrollBar()->setRange(0, theScrollHeight - height());
+ horizontalScrollBar()->setPageStep(width());
+ verticalScrollBar()->setPageStep(height());
+ horizontalScrollBar()->setVisible(true);
+ verticalScrollBar()->setVisible(true);
+ }
+}
+
+//==============================================================================
+/**
+ * OnRulerGuideToggled:
+ * Handle scrollbar position when ruler, guide has been toggled
+ *
+ */
+//==============================================================================
+void CPlayerContainerWnd::OnRulerGuideToggled()
+{
+ int scrollAmount = g_StudioApp.GetRenderer().AreGuidesEnabled() ? 16 : -16;
+ bool hasHorz = horizontalScrollBar()->isVisible();
+ bool hasVert = verticalScrollBar()->isVisible();
+ int hscrollPos = 0, vscrollPos = 0;
+ if (hasHorz) {
+ hscrollPos = qMax(horizontalScrollBar()->value() + scrollAmount, 0);
+ }
+ if (hasVert) {
+ vscrollPos = qMax(verticalScrollBar()->value() + scrollAmount, 0);
+ }
+ horizontalScrollBar()->setValue(hscrollPos);
+ verticalScrollBar()->setValue(vscrollPos);
+ m_PlayerWnd->update();
+}
+
+//==============================================================================
+/**
+ * RecenterClient: Recenters the Client rect in the View's client area.
+ */
+//==============================================================================
+void CPlayerContainerWnd::RecenterClient()
+{
+ QRect theViewClientRect = rect();
+ QSize theClientSize;
+ m_ClientRect = theViewClientRect;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ if (ShouldHideScrollBars()) {
+ } else
+#endif
+ {
+ theClientSize = GetEffectivePresentationSize();
+
+ // Only center if we need to scroll
+ if (theClientSize.width() > theViewClientRect.width()) {
+ // compute the size of the client rectangle to display
+ m_ClientRect.setLeft(
+ (theViewClientRect.width() / 2) - (theClientSize.width() / 2) - (theClientSize.width() % 2));
+ m_ClientRect.setRight((theViewClientRect.width() / 2) + (theClientSize.width() / 2));
+ }
+
+ if (theClientSize.height() > theViewClientRect.height()) {
+ m_ClientRect.setTop(
+ (theViewClientRect.height() / 2) - (theClientSize.height() / 2) - (theClientSize.height() % 2));
+ m_ClientRect.setBottom((theViewClientRect.height() / 2) + (theClientSize.height() / 2));
+ }
+ }
+
+ QRect glRect = m_ClientRect;
+ glRect.setWidth(int(devicePixelRatio() * m_ClientRect.width()));
+ glRect.setHeight(int(devicePixelRatio() * m_ClientRect.height()));
+ g_StudioApp.GetRenderer().SetViewRect(glRect);
+}
+
+//==============================================================================
+/**
+ * OnLButtonDown: Called whenever the user left clicks in the view.
+ * This processes the WM_LBUTTONDOWN message. This message is generated whenever
+ * the user left clicks in the view. Since this could involve selection of an item
+ * in the scene, it may (if the click is in the Client rect) call ProcessMouseClick()
+ * on the Document to perform the selection.
+ * @param inFlags the flags passed in from the message call
+ * @param inPoint the point where the event takes place
+ */
+void CPlayerContainerWnd::mousePressEvent(QMouseEvent *event)
+{
+ if ((event->button() == Qt::LeftButton) || (event->button() == Qt::RightButton)) {
+ long theToolMode = g_StudioApp.GetToolMode();
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDown(SceneDragSenderType::Matte, event->pos(),
+ theToolMode);
+ m_IsMouseDown = true;
+ } else if (event->button() == Qt::MiddleButton) {
+#ifdef INCLUDE_EDIT_CAMERA
+ const bool theCtrlKeyIsDown = event->modifiers() & Qt::ControlModifier;
+ const bool theAltKeyIsDown = event->modifiers() & Qt::AltModifier;
+
+ bool theToolChanged = false;
+ if (rect().contains(event->pos()) && !IsDeploymentView()) {
+ // If both the control key and the Alt key is not down
+ if (!theCtrlKeyIsDown && !theAltKeyIsDown) {
+ // press Scroll Wheel Click
+ // Do Camera Pan
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ theToolChanged = true;
+ } else if ((theAltKeyIsDown) && (!theCtrlKeyIsDown)) {
+ // press Alt-Scroll Wheel Click
+ // Do Camera Rotate if we are in 3D Camera
+ if (g_StudioApp.GetRenderer().DoesEditCameraSupportRotation(
+ g_StudioApp.GetRenderer().GetEditCamera())) {
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+ theToolChanged = true;
+ }
+ }
+ }
+
+ if (theToolChanged) {
+ Q_EMIT toolChanged();
+ m_SceneView->SetViewCursor();
+
+ long theToolMode = g_StudioApp.GetToolMode();
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDown(SceneDragSenderType::Matte,
+ event->pos(), theToolMode);
+ m_IsMouseDown = true;
+ m_IsMiddleMouseDown = true;
+ }
+#else
+ Q_UNUSED(inFlags);
+ Q_UNUSED(inPoint);
+#endif
+ }
+}
+
+//==============================================================================
+/**
+ * OnLButtonUp: Called whenever the user releases the left mouse button.
+ *
+ * This processes the WM_LBUTTONUP message. This message is generated whenever
+ * the left mouse button. We release the mouse capture to stop dragging.
+ *
+ * @param inFlags The flags passed in from the message call
+ * @param inPoint The point where the event takes place
+ */
+//==============================================================================
+void CPlayerContainerWnd::mouseReleaseEvent(QMouseEvent *event)
+{
+ if ((event->button() == Qt::LeftButton) || (event->button() == Qt::RightButton)) {
+ // Need to commit the current command when we have a mouse up. :)
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseUp(SceneDragSenderType::Matte);
+ g_StudioApp.GetCore()->CommitCurrentCommand();
+ m_IsMouseDown = false;
+ } else if (event->button() == Qt::MiddleButton) {
+ #ifdef INCLUDE_EDIT_CAMERA
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseUp(SceneDragSenderType::Matte);
+ g_StudioApp.GetCore()->CommitCurrentCommand();
+ if (m_IsMiddleMouseDown) {
+ m_IsMouseDown = false;
+ m_IsMiddleMouseDown = false;
+
+ const bool theCtrlKeyIsDown = event->modifiers() & Qt::ControlModifier;
+ const bool theAltKeyIsDown = event->modifiers() & Qt::AltModifier;
+
+ if (!IsDeploymentView()) {
+ if (!theCtrlKeyIsDown && !theAltKeyIsDown) {
+ // none of the modifier key is pressed... reset to previous tool
+ m_SceneView->RestorePreviousTool();
+ } else if (theCtrlKeyIsDown && theAltKeyIsDown) {
+ // since both modifier is down... let the ctrl has priority
+ m_SceneView->SetToolOnCtrl();
+ }
+ m_SceneView->SetViewCursor();
+ Q_EMIT toolChanged();
+ }
+ }
+ #endif
+ }
+}
+
+//==============================================================================
+/**
+ * OnMouseMove: Called whenever the user moves the mouse in the window.
+ *
+ * This processes the WM_MOUSEMOVE message. This message is generated whenever
+ * the user moves the mouse in the view. This tells lets the document process it
+ * as well since the user could be dragging an object.
+ *
+ * @param inFlags The flags passed in from the message call
+ * @param inPoint The point where the event takes place
+ */
+//==============================================================================
+void CPlayerContainerWnd::mouseMoveEvent(QMouseEvent* event)
+{
+ if (m_IsMouseDown) {
+ UICPROFILE(OnMouseMove);
+
+ long theModifierKeys = 0;
+ if (event->buttons() & Qt::LeftButton)
+ theModifierKeys = CHotKeys::MOUSE_LBUTTON | CHotKeys::GetCurrentKeyModifiers();
+ else if (event->buttons() & Qt::RightButton)
+ theModifierKeys = CHotKeys::MOUSE_RBUTTON | CHotKeys::GetCurrentKeyModifiers();
+
+ long theToolMode = g_StudioApp.GetToolMode();
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDrag(
+ SceneDragSenderType::Matte, event->pos(), theToolMode, theModifierKeys);
+ }
+}
+
+//==============================================================================
+/**
+ * OnMouseWheel: Called whenever the mouse wheel.
+ *
+ * This processes the WM_MOUSEWHEEL message.
+ *
+ * @param inFlags the flags passed in from the message call
+ * @param inPoint the point where the event takes place
+ */
+//==============================================================================
+void CPlayerContainerWnd::wheelEvent(QWheelEvent* event)
+{
+#ifdef INCLUDE_EDIT_CAMERA
+ // Note : Mouse wheel is a special animal of the scene drag tool. We dont change the tool
+ // so as not to affect the toolbar button and the view cursor. This will just do the zoom
+ // and the cursor is not changed.
+
+ const bool theCtrlKeyIsDown = event->modifiers() & Qt::ControlModifier;
+ const bool theAltKeyIsDown = event->modifiers() & Qt::AltModifier;
+
+ // Keeping these codes here, till we finalized the behavior and confirm these not needed
+ // long theToolMode = g_StudioApp.GetToolMode( );
+ //// If both the control key and the Alt key is not down
+ // if ( !theCtrlKeyIsDown && !theAltKeyIsDown && !IsDeploymentView( ) )
+ //{
+ // if ( theToolMode != STUDIO_TOOLMODE_CAMERA_ZOOM )
+ // {
+ // g_StudioApp.SetToolMode( STUDIO_TOOLMODE_CAMERA_ZOOM );
+ // theToolMode = STUDIO_TOOLMODE_CAMERA_ZOOM;
+ // m_MouseWheeling = true;
+
+ // Q_EMIT toolChanged();
+ // SetViewCursor( );
+ // }
+ //}
+
+ // Mouse Wheel
+ // Do Camera Zoom
+ if (!theCtrlKeyIsDown && !theAltKeyIsDown && !IsDeploymentView())
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseWheel(
+ SceneDragSenderType::Matte, event->delta(), STUDIO_TOOLMODE_CAMERA_ZOOM);
+#else
+ Q_UNUSED(event);
+#endif
+}
+
+void CPlayerContainerWnd::scrollContentsBy(int, int)
+{
+ long x, y;
+ SetPlayerWndPosition(x, y);
+}
+
+//==============================================================================
+/**
+ * Set the view mode of the current scene view, whether we are in editing mode
+ * or deployment mode. For editing mode, we want to use the full scene area without
+ * any matte area.
+ * @param inViewMode the view mode of this scene
+ */
+void CPlayerContainerWnd::SetViewMode(EViewMode inViewMode)
+{
+ m_ViewMode = inViewMode;
+ m_SceneView->RecheckSizingMode();
+ if (m_ViewMode == VIEW_SCENE) {
+ // switching from edit mode to deployment mode, release the edit camera tool and set it to
+ // object move
+ long theCurrentToolSettings = g_StudioApp.GetToolMode();
+ bool theIsCameraTool = (theCurrentToolSettings & STUDIO_CAMERATOOL_MASK ? true : false);
+ if (theIsCameraTool) {
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE);
+ m_SceneView->SetToolMode(STUDIO_TOOLMODE_MOVE);
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * return the view mode of the current scene view, whether we are in editing mode
+ * or deployment mode. For editing mode, we want to use the full scene area without
+ * any matte area.
+ * @return the current view mode
+ */
+CPlayerContainerWnd::EViewMode CPlayerContainerWnd::GetViewMode()
+{
+ return m_ViewMode;
+}
+
+//==============================================================================
+/**
+ * Checks whether we are in deployment view mode.
+ * @return true if is in deployment view mode, else false
+ */
+bool CPlayerContainerWnd::IsDeploymentView()
+{
+ return m_ViewMode == VIEW_SCENE ? true : false;
+}
+
+QSize CPlayerContainerWnd::GetEffectivePresentationSize() const
+{
+ CPt cSize = g_StudioApp.GetCore()->GetStudioProjectSettings()->GetPresentationSize();
+ QSize theSize(cSize.x, cSize.y);
+
+ // If we have guides, resize the window with enough space for the guides as well as the
+ // presentation
+ // This is a very dirty hack because we are of course hardcoding the size of the guides.
+ // If the size of the guides never changes, the bet paid off.
+ if (g_StudioApp.GetRenderer().AreGuidesEnabled()) {
+ theSize += QSize(32, 32);
+ }
+
+ return theSize / devicePixelRatio();
+}
+
+//==============================================================================
+
+void CPlayerContainerWnd::SetPlayerWnd(CPlayerWnd *inPlayerWnd)
+{
+ m_PlayerWnd = inPlayerWnd;
+ viewport()->setBackgroundRole(QPalette::Dark);
+ m_PlayerWnd->SetContainerWnd(this);
+ m_PlayerWnd->setParent(viewport());
+ m_PlayerWnd->setVisible(true);
+ m_PlayerWnd->resize(m_PlayerWnd->sizeHint());
+}
+
+//==============================================================================
+/**
+ * OnSize: Handles the WM_SIZE message
+ *
+ * Recenters the Client and recaluclates the matte when a resize message is
+ * generated.
+ *
+ * @param nType Specifies the type of resizing requested.
+ * @param cx Specifies the new width of the client area.
+ * @param cy Specifies the new height of the client area.
+ */
+//==============================================================================
+void CPlayerContainerWnd::resizeEvent(QResizeEvent* event)
+{
+ QAbstractScrollArea::resizeEvent(event);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ SetScrollRanges();
+#endif
+}
diff --git a/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.h b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.h
new file mode 100644
index 00000000..d4ac3cf5
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PLAYER_CONTAINER_WND_H
+#define INCLUDED_PLAYER_CONTAINER_WND_H 1
+
+#pragma once
+
+#include <QScrollArea>
+
+class CSceneView;
+class CStudioApp;
+class CPlayerWnd;
+class CWGLRenderContext;
+
+//==============================================================================
+// Class CPlayerContainerWnd
+//==============================================================================
+
+class CPlayerContainerWnd : public QAbstractScrollArea
+{
+ Q_OBJECT
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef enum {
+ VIEW_EDIT = 0, ///< Edit View
+ VIEW_SCENE, ///< Scene View
+ } EViewMode;
+
+public:
+ CPlayerContainerWnd(CSceneView *inSceneView);
+ virtual ~CPlayerContainerWnd();
+
+ void SetPlayerWnd(CPlayerWnd *inPlayerWnd);
+ void SetPlayerWndPosition(long &outLeftPresentationEdge, long &outTopPresentionEdge);
+ void SetScrollRanges();
+ void RecenterClient();
+ void OnRulerGuideToggled();
+
+ void SetViewMode(EViewMode inViewMode);
+ EViewMode GetViewMode();
+ bool IsDeploymentView();
+
+ QRect GetDisplayedClientRect() const { return m_ClientRect; }
+ bool IsMouseDown() const { return m_IsMouseDown; }
+ bool IsMiddleMouseDown() const { return m_IsMiddleMouseDown; }
+
+ QSize GetEffectivePresentationSize() const;
+
+Q_SIGNALS:
+ void toolChanged();
+
+protected:
+ void resizeEvent(QResizeEvent *) override;
+ void mousePressEvent(QMouseEvent *) override;
+ void mouseReleaseEvent(QMouseEvent *) override;
+ void mouseMoveEvent(QMouseEvent *) override;
+ void wheelEvent(QWheelEvent *) override;
+
+ void scrollContentsBy(int, int) override;
+
+private:
+ CPlayerContainerWnd() {}
+ bool ShouldHideScrollBars();
+
+protected:
+ CSceneView *m_SceneView; ///< Pointer to the SceneView for rulers manipulation
+ CPlayerWnd *m_PlayerWnd; ///< Pointer to the window control that contains client
+ QRect m_ClientRect; ///< The rect where the client is drawn
+ bool m_IsMouseDown; ///< true if the mouse (any button) is down
+ bool m_IsMiddleMouseDown; ///< true if the middle mouse ( or scroll wheel ) is down
+ EViewMode m_ViewMode;
+};
+
+#endif // INCLUDED_PLAYER_CONTAINER_WND_H
diff --git a/src/Authoring/Studio/_Win/UI/PlayerWnd.cpp b/src/Authoring/Studio/_Win/UI/PlayerWnd.cpp
new file mode 100644
index 00000000..ca9c7c51
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PlayerWnd.cpp
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "PlayerWnd.h"
+#include "MainFrm.h"
+#include "SceneView.h"
+#include "Dispatch.h"
+#include "MasterP.h"
+#include "HotKeys.h"
+#include "StudioApp.h"
+#include "Doc.h"
+#include "Dispatch.h"
+#include "HotKeys.h"
+#include "MouseCursor.h"
+#include "ResourceCache.h"
+#include "SceneDropTarget.h"
+#include "Core.h"
+#include "IDragable.h"
+#include "WGLRenderContext.h"
+#include "IStudioRenderer.h"
+
+#include <QMouseEvent>
+
+//==============================================================================
+// Class CPlayerWnd
+//==============================================================================
+
+CPlayerWnd::CPlayerWnd(QWidget *parent)
+ : QOpenGLWidget(parent)
+ , m_ContainerWnd(nullptr)
+ , m_IsMouseDown(false)
+ , m_PreviousToolMode(0)
+ , m_FitClientToWindow(false)
+{
+ m_LastKnownMousePosition = QPoint(-1, -1);
+
+ setAcceptDrops(true);
+ RegiserForDnd(this);
+ AddMainFlavor(EUIC_FLAVOR_FILE);
+ AddMainFlavor(EUIC_FLAVOR_ASSET_UICFILE);
+ AddMainFlavor(EUIC_FLAVOR_ASSET_LIB);
+ AddMainFlavor(EUIC_FLAVOR_BASIC_OBJECTS);
+
+ setFormat(CWGLRenderContext::selectSurfaceFormat(this));
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CPlayerWnd::~CPlayerWnd()
+{
+}
+
+//==============================================================================
+/**
+ * OnMouseMove: Handle the WM_MOUSEMOVE message
+ *
+ * @param inFlags flags passed in with th mouse move message
+ * @param inPoint where the mouse is
+ */
+//==============================================================================
+void CPlayerWnd::mouseMoveEvent(QMouseEvent *event)
+{
+ if (event->buttons() & Qt::MiddleButton) {
+ // Middle button events are handled by the parent CPlayerContainerWnd
+ event->ignore();
+ } else {
+ if (m_IsMouseDown) {
+ long theModifierKeys = 0;
+ if (event->buttons() & Qt::LeftButton)
+ theModifierKeys = CHotKeys::MOUSE_LBUTTON | CHotKeys::GetCurrentKeyModifiers();
+ else if (event->buttons() & Qt::RightButton)
+ theModifierKeys = CHotKeys::MOUSE_RBUTTON | CHotKeys::GetCurrentKeyModifiers();
+
+ long theToolMode = g_StudioApp.GetToolMode();
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDrag(
+ SceneDragSenderType::SceneWindow, event->pos(), theToolMode, theModifierKeys);
+ } else {
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseMove(
+ SceneDragSenderType::SceneWindow, event->pos());
+ }
+ }
+}
+
+//==============================================================================
+/**
+ * OnSize: Handle the WM_SIZE message
+ *
+ * @param nType Passed to the base class
+ * @param cx change in x window size
+ * @param cy change in y window size
+ */
+//==============================================================================
+void CPlayerWnd::resizeEvent(QResizeEvent *event)
+{
+ QOpenGLWidget::resizeEvent(event);
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CWnd *theChildWnd = this->GetWindow(GW_CHILD);
+
+ if (theChildWnd != nullptr) {
+ CRect theWndRect;
+
+ // Set the child window at the same position as the parent
+ this->GetWindowRect(&theWndRect);
+
+ theChildWnd->ScreenToClient(&theWndRect);
+ theChildWnd->MoveWindow(&theWndRect, FALSE);
+ }
+#endif
+ update();
+}
+
+//==============================================================================
+/**
+ * OnLButtonDown: Handle the WM_LBUTTONDOWN message
+ *
+ * @param inFlags Flags passed in from the message
+ * @param inPoint The point wher the button was clicked
+ */
+//==============================================================================
+void CPlayerWnd::mousePressEvent(QMouseEvent *event)
+{
+ const Qt::MouseButton btn = event->button();
+ if ((btn == Qt::LeftButton) || (btn == Qt::RightButton)) {
+ long theToolMode = g_StudioApp.GetToolMode();
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDown(SceneDragSenderType::SceneWindow,
+ event->pos(), theToolMode);
+ m_IsMouseDown = true;
+ } else if (btn == Qt::MiddleButton) {
+ event->ignore();
+ }
+}
+
+//==============================================================================
+/**
+ * OnLButtonUp: Called whenever the user releases the left mouse button.
+ *
+ * This processes the WM_LBUTTONUP message. This message is generated whenever
+ * the left mouse button. We release the mouse capture to stop dragging.
+ *
+ * @param inFlags the flags passed in from the message call
+ * @param the point where the lbutton up takes place
+ */
+//==============================================================================
+void CPlayerWnd::mouseReleaseEvent(QMouseEvent *event)
+{
+ const Qt::MouseButton btn = event->button();
+ if ((btn == Qt::LeftButton) || (btn == Qt::RightButton)) {
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseUp(SceneDragSenderType::SceneWindow);
+ g_StudioApp.GetCore()->CommitCurrentCommand();
+ m_IsMouseDown = false;
+ } else if (btn == Qt::MiddleButton) {
+ event->ignore();
+ }
+}
+
+void CPlayerWnd::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDblClick(
+ SceneDragSenderType::SceneWindow, event->pos());
+}
+
+
+bool CPlayerWnd::OnDragWithin(CDropSource &inSource)
+{
+ CSceneViewDropTarget theTarget;
+ return theTarget.Accept(inSource);
+}
+bool CPlayerWnd::OnDragReceive(CDropSource &inSource)
+{
+ CSceneViewDropTarget theTarget;
+ Q_EMIT dropReceived();
+ return theTarget.Drop(inSource);
+}
+void CPlayerWnd::OnDragLeave()
+{
+}
+
+//==============================================================================
+/**
+ * SetContainerWnd: keep track of a pointer to the containing window
+ *
+ * @param inContainerWnd pointer to what the containing window will be set to
+ */
+//==============================================================================
+void CPlayerWnd::SetContainerWnd(CPlayerContainerWnd *inContainerWnd)
+{
+ m_ContainerWnd = inContainerWnd;
+ updateGeometry();
+}
+
+QSize CPlayerWnd::sizeHint() const
+{
+ if (m_ContainerWnd)
+ return m_ContainerWnd->GetEffectivePresentationSize();
+ else
+ return QOpenGLWidget::sizeHint();
+}
+
+void CPlayerWnd::initializeGL()
+{
+ Q3DStudio::IStudioRenderer &theRenderer(g_StudioApp.GetRenderer());
+ if (theRenderer.IsInitialized() == false) {
+ try {
+ theRenderer.Initialize(this);
+ } catch (...) {
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+ wchar_t theBufferString[MAX_ENTRY_LENGTH];
+
+ _aswprintf(theBufferString, MAX_ENTRY_LENGTH - 1,
+ L"Unable to initialize OpenGL.\nThis may be because your graphic device is "
+ L"not sufficient, or simply because your driver is too old.\n\nPlease try "
+ L"upgrading your graphics driver and try again.");
+ ::wcsncat(theBufferString, L"\r\n\r\n", MAX_ENTRY_LENGTH - 1);
+
+ ::MessageBoxW(nullptr, theBufferString, L"Fatal Error",
+ MB_OK | MB_ICONSTOP | MB_DEFBUTTON1);
+#endif
+ exit(1);
+ }
+ }
+}
+
+void CPlayerWnd::paintGL()
+{
+ Q3DStudio::IStudioRenderer &theRenderer(g_StudioApp.GetRenderer());
+ // don't use request render here, this has to be
+ // synchronous inside paintGL
+ theRenderer.RenderNow();
+}
+
+void CPlayerWnd::resizeGL(int width, int height)
+{
+ // this also passes the new FBO to the CWGLContext
+ Q3DStudio::IStudioRenderer &theRenderer(g_StudioApp.GetRenderer());
+ theRenderer.SetViewRect(QRect(0, 0, width * devicePixelRatio(),
+ height * devicePixelRatio()));
+}
diff --git a/src/Authoring/Studio/_Win/UI/PlayerWnd.h b/src/Authoring/Studio/_Win/UI/PlayerWnd.h
new file mode 100644
index 00000000..25dfd949
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PlayerWnd.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PLAYERWND_H
+#define INCLUDED_PLAYERWND_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "DropContainer.h"
+#include "PlayerContainerWnd.h"
+
+#include <QOpenGLWidget>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CPlayerContainerWnd;
+class CStudioApp;
+class CMouseCursor;
+class CHotkeys;
+
+//==============================================================================
+// Class CPlayerWnd
+//==============================================================================
+
+class CPlayerWnd : public QOpenGLWidget, public CWinDropContainer
+{
+ Q_OBJECT
+public:
+ explicit CPlayerWnd(QWidget *parent = nullptr);
+ ~CPlayerWnd();
+
+ void SetContainerWnd(CPlayerContainerWnd *inSceneView);
+
+ QSize sizeHint() const override;
+
+ bool OnDragWithin(CDropSource &inSource) override;
+ bool OnDragReceive(CDropSource &inSource) override;
+ void OnDragLeave() override;
+ void OnReflectMouse(CPt &inPoint, Qt::KeyboardModifiers inFlags) override {}
+
+protected:
+
+ CPlayerContainerWnd *m_ContainerWnd;
+ bool m_IsMouseDown;
+ long m_PreviousToolMode; ///< The previous tool mode (used when toggling with hotkeys to switch
+ ///back to previous mode on release)
+ bool m_FitClientToWindow; ///< True if we are in Fit to Window Mode
+
+ QPoint m_LastKnownMousePosition;
+
+Q_SIGNALS:
+ void dropReceived();
+
+protected:
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void resizeEvent(QResizeEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseDoubleClickEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+
+ void initializeGL() override;
+ void paintGL() override;
+ void resizeGL(int width, int height) override;
+};
+
+#endif // INCLUDED_PLAYERWND_H
diff --git a/src/Authoring/Studio/_Win/UI/PopupWnd.cpp b/src/Authoring/Studio/_Win/UI/PopupWnd.cpp
new file mode 100644
index 00000000..f0b5d2cd
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PopupWnd.cpp
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PopupWnd.h"
+#include "AppFonts.h"
+
+#include "StudioPreferences.h"
+
+//==============================================================================
+/**
+ * Constructor: Initialize the object.
+ *
+ * Creates default fonts, colors, etc.
+ */
+CPopupWnd::CPopupWnd()
+ : m_CenterPt(0, 0)
+ , m_IsStationary(false)
+{
+ // get the proper font from appfonts
+ m_Font = CAppFonts::GetInstance()->GetNormalFont();
+
+ // Set the default colors (use default system tooltip colors)
+ m_TextColor = ::GetSysColor(COLOR_INFOTEXT);
+ m_BkColor = ::GetSysColor(COLOR_INFOBK);
+ ::CColor theBGColor(CStudioPreferences::GetTooltipBackgroundColor());
+ m_BkColor = theBGColor.GetRGBColor();
+ m_BkBrush = new CBrush();
+ m_BkBrush->CreateSolidBrush(m_BkColor);
+}
+
+//==============================================================================
+/**
+ * Destructor: Destroys the object and releases associated memory.
+ */
+CPopupWnd::~CPopupWnd()
+{
+ // Clean up GDI objects
+
+ // m_Font.DeleteObject();
+
+ if (m_BkBrush) {
+ DeleteObject(m_BkBrush);
+ delete m_BkBrush;
+ }
+}
+
+//==============================================================================
+// Message Map
+//==============================================================================
+BEGIN_MESSAGE_MAP(CPopupWnd, CWnd)
+//{{AFX_MSG_MAP(CPopupWnd)
+ON_WM_PAINT()
+ON_WM_ERASEBKGND()
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * OnPaint: Handles the WM_PAINT windows message.
+ *
+ * Calls GetWindowText() and draws the text to the screen.
+ */
+void CPopupWnd::OnPaint()
+{
+ CPaintDC theDC(this); // device context for painting
+ CString theText;
+
+ GetWindowText(theText);
+ if (theText.GetLength() > 0) {
+
+ // Change the font
+ CFont *theOldFont = theDC.SelectObject(m_Font);
+ theDC.SetTextColor(m_TextColor);
+ theDC.SetBkColor(m_BkColor);
+
+ // Paint the text
+ CRect theClientRect;
+ this->GetClientRect(theClientRect);
+ theDC.DrawText(theText, theClientRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
+
+ // Restore original font
+ theDC.SelectObject(theOldFont);
+ }
+}
+
+//==============================================================================
+/**
+ * SetWindowText: Sets the text for this window.
+ *
+ * Overridden from parent so that we can calculate how big we need to make the
+ * pop-up window so that the text fits. Automatically adjusts the window
+ * size/position to fit the new text string.
+ */
+void CPopupWnd::SetWindowText(LPCTSTR lpszString)
+{
+ CString theNewText;
+ theNewText.Format(L" %s ", lpszString);
+
+ // Set the window text
+ CWnd::SetWindowText(theNewText);
+
+ // Calculate the new window rect with the specified text
+ CDC *theDC = GetDC();
+ CRect theRect(0, 0, 1, 1);
+ CFont *theOldFont = theDC->SelectObject(m_Font);
+
+ theDC->DrawText(theNewText, theRect, DT_CALCRECT);
+ theDC->SelectObject(theOldFont);
+ ::AdjustWindowRect(theRect, this->GetStyle(), FALSE);
+ CPoint theTopLeft = theRect.TopLeft();
+ CPoint theBottomRight = theRect.BottomRight();
+ ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theTopLeft);
+ ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theBottomRight);
+ CRect theAdjustedRect(theTopLeft, theBottomRight);
+ int theX = abs((int)(theAdjustedRect.Width() / 2) - m_CenterPt.x);
+ int theY = abs((int)(theAdjustedRect.Height() / 2) - m_CenterPt.y);
+
+ ReleaseDC(theDC);
+
+ // Move the window to the new position, with the new size, still centered at m_CenterPt
+ this->SetWindowPos(nullptr, theX, theY, theAdjustedRect.Width(), theAdjustedRect.Height(),
+ SWP_NOZORDER | SWP_NOACTIVATE);
+}
+
+//==============================================================================
+/**
+ * SetCenterPoint: Changes the center of this window.
+ *
+ * Use this function to specify where you want the center of the pop-up window
+ * to appear. The window is automatically moved to the new center position.
+ */
+void CPopupWnd::SetCenterPoint(CPoint inPoint)
+{
+ if ((m_IsStationary && !IsWindowVisible()) || !m_IsStationary) {
+ // Store the center point
+ m_CenterPt = inPoint;
+
+ // Calculate the new window position so that it is centered at the new point
+ CRect theWindowRect;
+ this->GetWindowRect(theWindowRect);
+ CPoint theTopLeft = theWindowRect.TopLeft();
+ CPoint theBottomRight = theWindowRect.BottomRight();
+ ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theTopLeft);
+ ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theBottomRight);
+ CRect theAdjustedRect(theTopLeft, theBottomRight);
+ int theX = abs((int)(theAdjustedRect.Width() / 2) - m_CenterPt.x);
+ int theY = abs((int)(theAdjustedRect.Height() / 2) - m_CenterPt.y);
+
+ // Move the window
+ SetWindowPos(nullptr, theX, theY, theAdjustedRect.Width(), theAdjustedRect.Height(),
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+}
+
+//==============================================================================
+/**
+ * SetBkColor: Changes the background color of this window.
+ *
+ * Defaults to COLOR_INFOBK (tooltip background color). Creates a brush used
+ * in OnEraseBkgnd() of the specified color.
+ *
+ * @param inColor The new background color.
+ */
+void CPopupWnd::SetBkColor(COLORREF inColor)
+{
+ m_BkColor = inColor;
+
+ // If we already have a background brush
+ if (m_BkBrush) {
+ // Kill it
+ DeleteObject(m_BkBrush);
+ delete m_BkBrush;
+ }
+
+ // Make a brush of the specified color
+ m_BkBrush = new CBrush();
+ m_BkBrush->CreateSolidBrush(m_BkColor);
+}
+
+//==============================================================================
+/**
+ * OnEraseBkgnd: Handles the WM_ERASEBKGND windows message.
+ * Redraws the client rect using the current background brush.
+ *
+ * @param pDC Pointer to a display context for drawing.
+ * @return TRUE.
+ */
+BOOL CPopupWnd::OnEraseBkgnd(CDC *pDC)
+{
+ // Erase the client rect using the background brush so it's the right color
+ CRect theClientRect;
+ this->GetClientRect(theClientRect);
+ pDC->FillRect(theClientRect, m_BkBrush);
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * UpdateToolTip: Allows you to change multiple properties on this window at once.
+ *
+ * @param inCenter New center point of the popup window
+ * @param inText New window text for the window
+ * @param inShowWindow true to show the window, false to hide the window
+ */
+void CPopupWnd::UpdateToolTip(CPoint inCenter, CString inText, bool inShowWindow)
+{
+ int theShowFlag = (inShowWindow) ? SW_SHOWNA : SW_HIDE;
+
+ this->SetCenterPoint(inCenter);
+ this->SetWindowText(inText);
+ this->ShowWindow(theShowFlag);
+ this->Invalidate(FALSE);
+ this->UpdateWindow();
+}
diff --git a/src/Authoring/Studio/_Win/UI/PopupWnd.h b/src/Authoring/Studio/_Win/UI/PopupWnd.h
new file mode 100644
index 00000000..da58c9b1
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PopupWnd.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_POP_UP_WND
+#define INCLUDED_POP_UP_WND 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//==============================================================================
+/**
+ * CPopupWnd: Class for making pop-up windows (a replacement for tooltips).
+ *
+ * To use, just create a CPopupWnd, set the text that you want displayed, then
+ * call ShowWindow() to toggle the window on and off. Default color scheme of
+ * this window mimics the system settings for tooltips.
+ */
+class CPopupWnd : public CWnd
+{
+public:
+ CPopupWnd();
+
+ virtual ~CPopupWnd();
+
+ /// Sets the text to display in this window
+ void SetWindowText(LPCTSTR lpszString);
+
+ /// Sets the center point of this window in screen coordinates
+ void SetCenterPoint(CPoint inPoint);
+
+ /// Sets the center point of this window from an x,y pair (screen coordinates)
+ void SetCenterPoint(int inX, int inY) { SetCenterPoint(CPoint(inX, inY)); }
+
+ /// Retrieves the center point of this window (screen coordinates)
+ CPoint GetCenterPoint() { return m_CenterPt; }
+
+ /// Sets the color of the text
+ void SetTextColor(COLORREF inColor) { m_TextColor = inColor; }
+
+ /// Sets the background color of the window
+ void SetBkColor(COLORREF inColor);
+
+ /// Returns a pointer to the CFont object used to draw the text. You can make changes to the
+ /// font using the pointer that's returned,
+ /// just don't delete it. The default font is set in the constructor as Arial 13.
+ CFont *GetFont() { return m_Font; }
+
+ /// Allows you to change multiple properties on this window at once.
+ void UpdateToolTip(CPoint inCenter, CString inText, bool inShowWindow);
+
+ ///
+ void SetStationary(bool inIsStationary) { m_IsStationary = inIsStationary; }
+
+protected:
+ CPoint m_CenterPt; ///< Center of this window in screen coordinates
+ CFont *m_Font; ///< Font for the window text
+ COLORREF m_TextColor; ///< Color of the text
+ COLORREF m_BkColor; ///< Background color of the window
+ CBrush *m_BkBrush; ///< Brush used for paiting the background of the window
+ bool m_IsStationary; ///< If the window is stationary, then it can only be moved while it is not
+ ///showing
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CPopupWnd)
+ afx_msg void OnPaint();
+ afx_msg BOOL OnEraseBkgnd(CDC *pDC);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif // INCLUDED_POP_UP_WND
diff --git a/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.cpp b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.cpp
new file mode 100644
index 00000000..649efa8c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#include "stdafx.h"
+
+#pragma warning(disable : 4127)
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "PreviewOutputDlg.h"
+#include "StudioClipboard.h"
+#include "UICFileTools.h"
+#include "StudioApp.h"
+#include "Doc.h"
+#include "Mainfrm.h"
+#include "Dialogs.h"
+#include "Strings.h"
+#include "Resource.h"
+#include "Core.h"
+
+// CPreviewOutput dialog
+
+IMPLEMENT_DYNAMIC(CPreviewOutputDlg, CDialog)
+
+CPreviewOutputDlg::CPreviewOutputDlg(const Q3DStudio::CString &inCmd,
+ const Q3DStudio::CString &inExportedFile,
+ CPreviewHelper::EExecMode inViewMode)
+ : CDialog(CPreviewOutputDlg::IDD, nullptr)
+ , m_Cmd(inCmd)
+ , m_ExportedFile(inExportedFile)
+ , m_ViewMode(inViewMode)
+ , m_ReadThreadHandle(nullptr)
+ , m_PreviewProcessHandle(nullptr)
+{
+ m_OutputReadThreadParam.m_ReadHandle = nullptr;
+ m_OutputReadThreadParam.m_Context = nullptr;
+}
+
+CPreviewOutputDlg::~CPreviewOutputDlg()
+{
+ if (m_ReadThreadHandle) {
+ TerminateThread(m_ReadThreadHandle, 0);
+ m_ReadThreadHandle = nullptr;
+ }
+
+ if (m_OutputReadThreadParam.m_ReadHandle) {
+ CloseHandle(m_OutputReadThreadParam.m_ReadHandle);
+ m_OutputReadThreadParam.m_ReadHandle = nullptr;
+ }
+}
+
+void CPreviewOutputDlg::DoDataExchange(CDataExchange *pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_LIST_PREVIEW_STATUS, m_ListCtrl);
+}
+
+//=============================================================================
+/**
+ * Message Handler when dialog is initially opened.
+ */
+//=============================================================================
+BOOL CPreviewOutputDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ // Set the dialog header
+ Q3DStudio::CString theFile = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath().GetName();
+ if (theFile == "")
+ theFile = ::LoadResourceString(IDS_UNTITLED_DOCUMENT_TITLE);
+ Q3DStudio::CString theDlgHeader;
+ Q3DStudio::CString theOperation;
+ switch (m_ViewMode) {
+ case CPreviewHelper::EXECMODE_PREVIEW:
+ theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_PREVIEW);
+ break;
+
+ case CPreviewHelper::EXECMODE_DEPLOY:
+ theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_DEPLOY);
+ break;
+ }
+ theDlgHeader.Format(::LoadResourceString(IDS_CONFIG_PREVIEW_TITLE),
+ static_cast<const wchar_t *>(theOperation),
+ static_cast<const wchar_t *>(theFile));
+ SetWindowText(theDlgHeader);
+
+ // Prepare the list control
+ COLORREF theColor = 0x00C0C0C0;
+ m_ListCtrl.SetBkColor(theColor);
+ m_ListCtrl.SetTextBkColor(theColor);
+ CRect theRect;
+ m_ListCtrl.GetClientRect(theRect);
+ m_ListCtrl.InsertColumn(0, L"", LVCFMT_LEFT,
+ theRect.Width() * 2); // Double the width to see more
+
+ // Start the preview
+ if (!ExecutePreview()) {
+ CUICFile thePreviewerFile(CUICFile::GetApplicationDirectory(), m_ExportedFile);
+ Q3DStudio::CString theMessage;
+ theMessage.Format(::LoadResourceString(IDS_CONFIG_PREVIEW_ERROR_MSG),
+ static_cast<const wchar_t *>(thePreviewerFile.GetAbsolutePosixPath()));
+ g_StudioApp.GetDialogs()->DisplayMessageBox(
+ ::LoadResourceString(IDS_CONFIG_PREVIEW_ERROR_TITLE), theMessage,
+ CUICMessageBox::ICON_ERROR, false);
+ }
+
+ return TRUE;
+}
+
+//=============================================================================
+/**
+ * Handler for copying
+ */
+//=============================================================================
+void CPreviewOutputDlg::OnCopyText()
+{
+ try {
+ Q3DStudio::CString theText = "";
+ int theNumEntry = m_ListCtrl.GetItemCount();
+ for (int theIndex = 0; theIndex < theNumEntry; ++theIndex) {
+ theText += m_ListCtrl.GetItemText(theIndex, 0);
+ theText += "\r\n";
+ }
+ CStudioClipboard::CopyTextToClipboard(theText);
+ } catch (...) {
+ }
+}
+
+//=============================================================================
+/**
+ * Handler for OK Button
+ */
+//=============================================================================
+void CPreviewOutputDlg::OnOK()
+{
+ TerminateThread(m_ReadThreadHandle, 0);
+ CDialog::OnOK();
+ m_ReadThreadHandle = nullptr;
+}
+
+BEGIN_MESSAGE_MAP(CPreviewOutputDlg, CDialog)
+ON_BN_CLICKED(IDC_BUTTON_COPY_TEXT, OnCopyText)
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * Spawn the process to execute the preview operation and redirect it's output
+ * to the list control
+ */
+//==============================================================================
+BOOL CPreviewOutputDlg::ExecutePreview()
+{
+ HANDLE theOutputReadHandleTmp;
+ HANDLE theOutputReadHandle;
+ HANDLE theOutputWriteHandle;
+
+ // Set up the security attributes struct.
+ SECURITY_ATTRIBUTES theSecurityAttr;
+ theSecurityAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ theSecurityAttr.lpSecurityDescriptor = nullptr;
+ theSecurityAttr.bInheritHandle = TRUE;
+
+ // Create the child output pipe.
+ if (!CreatePipe(&theOutputReadHandleTmp, &theOutputWriteHandle, &theSecurityAttr, 0))
+ return FALSE;
+
+ // Create new output read handle. Set the Properties to FALSE.
+ // Otherwise, the child inherits the properties and, as a result,
+ // non-closeable handles to the pipes are created.
+ if (!DuplicateHandle(GetCurrentProcess(), theOutputReadHandleTmp, GetCurrentProcess(),
+ &theOutputReadHandle, // Address of new handle.
+ 0, FALSE, // Make it uninheritable.
+ DUPLICATE_SAME_ACCESS))
+ return FALSE;
+
+ // Close inheritable copies of the handles you do not want to be inherited.
+ CloseHandle(theOutputReadHandleTmp);
+
+ LaunchPreviewProcess(theOutputWriteHandle, m_Cmd);
+
+ // Close pipe handles (do not continue to modify the parent).
+ // You need to make sure that no handles to the write end of the
+ // output pipe are maintained in this process or else the pipe will
+ // not close when the child process exits and the ReadFile will hang.
+ CloseHandle(theOutputWriteHandle);
+
+ // Spawn a thread to busy read the preivew process output.
+ DWORD theThreadId;
+ m_OutputReadThreadParam.m_Context = this;
+ m_OutputReadThreadParam.m_ReadHandle = theOutputReadHandle;
+ m_ReadThreadHandle = CreateThread(nullptr, 0, CPreviewOutputDlg::ReadOutputThread,
+ (LPVOID)&m_OutputReadThreadParam, 0, &theThreadId);
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * Callback when the preview operation has completed.
+ */
+//==============================================================================
+void CPreviewOutputDlg::PreviewProcessTerminated()
+{
+ DWORD theExitCode;
+ GetExitCodeProcess(m_PreviewProcessHandle, &theExitCode);
+ if (theExitCode == 0)
+ PostMessage(WM_CLOSE); // close the window
+ else {
+ Q3DStudio::CString theOperation;
+ switch (m_ViewMode) {
+ case CPreviewHelper::EXECMODE_PREVIEW:
+ theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_PREVIEW);
+ break;
+
+ case CPreviewHelper::EXECMODE_DEPLOY:
+ theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_DEPLOY);
+ break;
+ }
+ Q3DStudio::CString theMessage;
+ theMessage.Format(::LoadResourceString(IDS_CONFIG_PREVIEW_ERROR_TEXT),
+ static_cast<const wchar_t *>(theOperation));
+ DisplayOutput(theMessage);
+ }
+}
+
+//==============================================================================
+/**
+ * Write the string into the list control.
+ * @param inString the string to display
+ */
+//==============================================================================
+void CPreviewOutputDlg::DisplayOutput(CString inStr)
+{
+ const wchar_t *DELIMITERS = L"\r\t\n";
+
+ wchar_t theBuffer[512] = { 0 };
+ ::wcscpy(theBuffer, inStr);
+
+ wchar_t *theToken = ::wcstok(theBuffer, DELIMITERS);
+ while (theToken) {
+ m_ListCtrl.InsertItem(m_ListCtrl.GetItemCount(), theToken);
+ theToken = ::wcstok(nullptr, DELIMITERS);
+ }
+
+ m_ListCtrl.EnsureVisible(m_ListCtrl.GetItemCount() - 1, FALSE);
+}
+
+//==============================================================================
+/**
+ * Spawn the process to execute the preview operation
+ * @param inStdOutput the handle to write the output to
+ * @param inCmd the command to execute
+ * @return true is spawned successfully, else false
+ */
+//==============================================================================
+BOOL CPreviewOutputDlg::LaunchPreviewProcess(HANDLE inStdOutput, Q3DStudio::CString &inCmd)
+{
+ // Further usability hax, you love them.
+ DisplayOutput(L"Checking for .NET Framework install:");
+ HKEY theHKey;
+ if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP", 0,
+ KEY_QUERY_VALUE, &theHKey)) {
+ DisplayOutput(L" - OK: .NET Framework present.");
+ } else {
+ DisplayOutput(L" - WARNING: .NET Framework Missing?");
+ }
+
+ // Launch the process with the working directory set to the parent directory of current document
+ CUICFile theDocument = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath();
+
+ Q3DStudio::CString theWorkingPath;
+ if (theDocument.Exists())
+ theWorkingPath = theDocument.GetAbsolutePath();
+ else
+ theWorkingPath = m_ExportedFile;
+
+ CUICFile thePreviewerFile(CUICFile::GetApplicationDirectory(), theWorkingPath);
+ Q3DStudio::CFilePath theWorkingDirectory(thePreviewerFile.GetAbsolutePosixPath());
+
+ PROCESS_INFORMATION theProcessInfo;
+ STARTUPINFO theStartupInfo;
+
+ // Set up the start up info struct.
+ ZeroMemory(&theStartupInfo, sizeof(STARTUPINFO));
+ theStartupInfo.cb = sizeof(STARTUPINFO);
+ theStartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+ theStartupInfo.hStdOutput = inStdOutput;
+ theStartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE) /*hChildStdIn*/;
+ theStartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ theStartupInfo.wShowWindow = SW_HIDE;
+
+ if (!CreateProcess(nullptr, const_cast<wchar_t *>(inCmd.c_str()), nullptr, nullptr, TRUE, 0, nullptr,
+ theWorkingDirectory.GetDirectory(), &theStartupInfo, &theProcessInfo))
+ return FALSE;
+
+ // Close any unnecessary handles.
+ CloseHandle(theProcessInfo.hThread);
+ m_PreviewProcessHandle = theProcessInfo.hProcess;
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * Spawn the thread to busy read the output and write to the list control
+ * @param inThreadParam the parameter used by this thread
+ * @return 1
+ */
+//==============================================================================
+DWORD WINAPI CPreviewOutputDlg::ReadOutputThread(LPVOID inThreadParam)
+{
+ char theBuffer[512];
+ DWORD theBytesRead;
+ SThreadParam *theParam = (SThreadParam *)inThreadParam;
+ HANDLE thePipeRead = theParam->m_ReadHandle;
+ CPreviewOutputDlg *theDlg = (CPreviewOutputDlg *)(theParam->m_Context);
+
+ while (TRUE) {
+ if (!ReadFile(thePipeRead, theBuffer, sizeof(theBuffer) - sizeof(char), &theBytesRead, nullptr)
+ || !theBytesRead) {
+ if (GetLastError() == ERROR_BROKEN_PIPE) {
+ theDlg->PreviewProcessTerminated();
+ CloseHandle(thePipeRead);
+ theParam->m_ReadHandle = nullptr;
+ break; // pipe done - normal exit path.
+ } else
+ theDlg->DisplayOutput(::LoadResourceString(
+ IDS_CONFIG_PREVIEW_REDIRECT_ERROR)); // Something bad happened.
+ } else {
+ if (theBytesRead) {
+ theBuffer[theBytesRead] = '\0'; // Follow input with a nullptr.
+ theDlg->DisplayOutput(CString(theBuffer));
+ }
+ }
+ }
+ return 1;
+}
diff --git a/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.h b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.h
new file mode 100644
index 00000000..19361d3d
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_PREVIEW_OUTPUT_DIALOG_H
+#define INCLUDED_PREVIEW_OUTPUT_DIALOG_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "resource.h"
+#include "PreviewHelper.h"
+
+//==============================================================================
+// Forwards
+//==============================================================================
+namespace Q3DStudio {
+class CFilePath;
+}
+
+class CPreviewOutputDlg : public CDialog
+{
+ DECLARE_DYNAMIC(CPreviewOutputDlg)
+
+protected:
+ struct SThreadParam
+ {
+ void *m_Context;
+ HANDLE m_ReadHandle;
+ };
+
+public:
+ CPreviewOutputDlg(const Q3DStudio::CString &inCmd, const Q3DStudio::CString &inExportedFile,
+ CPreviewHelper::EExecMode inViewMode);
+ virtual ~CPreviewOutputDlg();
+
+ // Dialog Data
+ enum { IDD = IDD_DIALOG_PREVIEW_STATUS };
+ CListCtrl m_ListCtrl;
+
+protected:
+ virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support
+ virtual BOOL OnInitDialog();
+ virtual void OnCopyText();
+ virtual void OnOK();
+ DECLARE_MESSAGE_MAP()
+
+protected:
+ BOOL ExecutePreview();
+ BOOL LaunchPreviewProcess(HANDLE inStdOutput, Q3DStudio::CString &inCmd);
+ static DWORD WINAPI ReadOutputThread(LPVOID lpvThreadParam);
+ void DisplayOutput(CString inStr);
+ void PreviewProcessTerminated();
+
+protected:
+ Q3DStudio::CString m_Cmd;
+ Q3DStudio::CString m_ExportedFile;
+ SThreadParam m_OutputReadThreadParam;
+ HANDLE m_PreviewProcessHandle;
+ HANDLE m_ReadThreadHandle;
+ CPreviewHelper::EExecMode m_ViewMode;
+};
+
+#endif // INCLUDED_PREVIEW_OUTPUT_DIALOG_H
diff --git a/src/Authoring/Studio/_Win/UI/RecentItems.cpp b/src/Authoring/Studio/_Win/UI/RecentItems.cpp
new file mode 100644
index 00000000..b229ff29
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/RecentItems.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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 "stdafx.h"
+
+#include "RecentItems.h"
+#include "Preferences.h"
+
+#include <QMenu>
+
+// using namespace Q3DStudio; <-- Do not do this here because it will conflict with CList and make
+// the template generator go blah
+
+const Q3DStudio::CString CRecentItems::RECENTITEM_KEY = "RecentItem";
+const Q3DStudio::CString CRecentItems::RECENTIMPORT_KEY = "RecentImport";
+const Q3DStudio::CString CRecentItems::RECENTITEM_VALID = "RecentValid";
+
+CRecentItems::CRecentItems(QMenu *inMenuID, long inCommandID, Q3DStudio::CString inPreferenceKey)
+{
+ Q_UNUSED(inCommandID)
+
+ m_Menu = inMenuID;
+ m_ValidItems = 10;
+ m_PreferenceKey = inPreferenceKey;
+
+ ReconstructList();
+}
+
+CRecentItems::~CRecentItems()
+{
+}
+
+void CRecentItems::AddRecentItem(const CUICFile &inItem)
+{
+ RemoveRecentItem(inItem);
+
+ m_RecentItems.insert(m_RecentItems.begin(), inItem);
+
+ while (m_RecentItems.size() > 10)
+ m_RecentItems.pop_back();
+
+ RebuildList();
+}
+
+void CRecentItems::RemoveRecentItem(const CUICFile &inItem)
+{
+ TFileList::iterator thePos = m_RecentItems.begin();
+ for (; thePos != m_RecentItems.end(); ++thePos) {
+ if ((*thePos) == inItem) {
+ m_RecentItems.erase(thePos);
+ break;
+ }
+ }
+
+ RebuildList();
+}
+
+void CRecentItems::ReconstructList()
+{
+ ClearMenu();
+ m_RecentItems.clear();
+
+ CPreferences thePrefs = CPreferences::GetUserPreferences();
+
+ m_ValidItems = thePrefs.GetLongValue(RECENTITEM_VALID, m_ValidItems);
+
+ for (long theIndex = 0; theIndex < (m_ValidItems > 10 ? 10 : m_ValidItems); ++theIndex) {
+ Q3DStudio::CString theKey;
+ theKey.Format(_UIC("%ls%d"), static_cast<const wchar_t *>(m_PreferenceKey), theIndex);
+
+ Q3DStudio::CString theFilename = thePrefs.GetStringValue(theKey, "");
+ if (theFilename != "") {
+ CUICFile theFile(theFilename);
+
+ QAction *act = m_Menu->addAction(theFile.GetName().toQString(),
+ this, &CRecentItems::onTriggerRecent);
+ act->setData(static_cast<int>(m_RecentItems.size()));
+ m_RecentItems.push_back(theFile);
+ }
+ }
+}
+
+void CRecentItems::RebuildList()
+{
+ ClearMenu();
+
+ CPreferences thePrefs = CPreferences::GetUserPreferences();
+ thePrefs.SetLongValue(RECENTITEM_VALID, GetItemCount());
+ TFileList::iterator thePos = m_RecentItems.begin();
+ for (long theIndex = 0; thePos != m_RecentItems.end(); ++thePos, ++theIndex) {
+ Q3DStudio::CString theFilename = (*thePos).GetName();
+
+ QAction *act = m_Menu->addAction(theFilename.toQString(),
+ this, &CRecentItems::onTriggerRecent);
+ act->setData(static_cast<int>(theIndex));
+
+ Q3DStudio::CString theKey;
+ theKey.Format(_UIC("%ls%d"), static_cast<const wchar_t *>(m_PreferenceKey), theIndex);
+
+ thePrefs.SetStringValue(theKey, (*thePos).GetAbsolutePath());
+ }
+}
+
+void CRecentItems::ClearMenu()
+{
+ m_Menu->clear();
+}
+
+CUICFile CRecentItems::GetItem(long inIndex)
+{
+ return m_RecentItems.at(inIndex);
+}
+
+void CRecentItems::onTriggerRecent()
+{
+ const int index = qobject_cast<QAction *>(sender())->data().toInt();
+ Q_EMIT openRecent(index);
+}
+
diff --git a/src/Authoring/Studio/_Win/UI/RecentItems.h b/src/Authoring/Studio/_Win/UI/RecentItems.h
new file mode 100644
index 00000000..bc295079
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/RecentItems.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_RECENT_ITEMS_H
+#define INCLUDED_RECENT_ITEMS_H 1
+
+#pragma once
+
+#include <QObject>
+
+#include "UICString.h"
+#include "UICFile.h"
+
+#include <vector>
+
+class CUICFile;
+
+QT_BEGIN_NAMESPACE
+class QMenu;
+QT_END_NAMESPACE
+
+class CRecentItems : public QObject
+{
+ Q_OBJECT
+
+ typedef std::vector<CUICFile> TFileList;
+
+public:
+ static const Q3DStudio::CString RECENTITEM_KEY;
+ static const Q3DStudio::CString RECENTIMPORT_KEY;
+ static const Q3DStudio::CString RECENTITEM_VALID;
+
+Q_SIGNALS:
+ void openRecent(int index);
+public:
+ CRecentItems(QMenu *inMenu, long inCommandID,
+ Q3DStudio::CString inPreferenceKey = RECENTITEM_KEY);
+ virtual ~CRecentItems();
+
+ void AddRecentItem(const CUICFile &inItem);
+ void RemoveRecentItem(const CUICFile &inItem);
+
+ CUICFile GetItem(long inIndex);
+ long GetItemCount() const { return (long)m_RecentItems.size(); }
+
+protected:
+ void ClearMenu();
+ void ReconstructList();
+ void RebuildList();
+ void SaveRecentList();
+
+ TFileList m_RecentItems;
+
+ long m_CommandID;
+ long m_ValidItems;
+ QMenu *m_Menu;
+ Q3DStudio::CString m_PreferenceKey;
+
+private Q_SLOTS:
+ void onTriggerRecent();
+};
+#endif // INCLUDED_RECENT_ITEMS_H
diff --git a/src/Authoring/Studio/_Win/UI/ReportDlg.cpp b/src/Authoring/Studio/_Win/UI/ReportDlg.cpp
new file mode 100644
index 00000000..2563a4c1
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ReportDlg.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+// ReportDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Strings.h"
+
+#include "ReportDlg.h"
+#include "CrashInfo.h"
+
+#include "CompConfig.h"
+
+#include "StudioInstance.h"
+#include <strstream>
+
+extern char g_DumpPath[MAX_PATH];
+/////////////////////////////////////////////////////////////////////////////
+// CReportDlg dialog
+
+CReportDlg::CReportDlg(CWnd *pParent /*=nullptr*/)
+ : CDialog(CReportDlg::IDD, pParent)
+ , m_SysInfoText(_T(""))
+{
+ //{{AFX_DATA_INIT(CReportDlg)
+ m_Info = _T("");
+ m_DescHeader = _T("");
+ m_EmailAddress = _T("");
+ m_EmailHeader = _T("");
+ //}}AFX_DATA_INIT
+
+ m_MediumFont2.CreatePointFont(88, CString(CStudioPreferences::GetFontFaceName()));
+
+ m_Color_Background = CStudioPreferences::GetDarkBaseColor();
+ m_Color_Text = CStudioPreferences::GetMasterColor();
+ m_Color_Gray = CStudioPreferences::GetNormalColor();
+ m_Color_Dark = CStudioPreferences::GetInactiveColor();
+}
+
+void CReportDlg::DoDataExchange(CDataExchange *pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CReportDlg)
+ DDX_Control(pDX, IDC_REPORTDLG_SYSINFO, m_SendSysInfo);
+ DDX_Control(pDX, IDC_REPORTDLG_DESC, m_Description);
+ DDX_Text(pDX, IDC_REPORTDLG_INFO, m_Info);
+ DDX_Text(pDX, IDC_REPORTDLG_DESCHEADER, m_DescHeader);
+ DDX_Text(pDX, IDC_REPORTDLG_EMAILADDR, m_EmailAddress);
+ DDX_Text(pDX, IDC_REPORTDLG_EMAILHEADER, m_EmailHeader);
+ //}}AFX_DATA_MAP
+ DDX_Text(pDX, IDC_CRASHDLG_SYSINFO_TEXT, m_SysInfoText);
+}
+
+BEGIN_MESSAGE_MAP(CReportDlg, CDialog)
+//{{AFX_MSG_MAP(CReportDlg)
+ON_BN_CLICKED(IDSUBMIT, OnSubmit)
+//}}AFX_MSG_MAP
+ON_WM_CTLCOLOR()
+ON_WM_ERASEBKGND()
+// ON_STN_CLICKED(IDC_REPORTDLG__SYSINFO_TEXT, &CReportDlg::OnStnClickedReportdlg)
+ON_STN_CLICKED(IDC_REPORTDLG__SYSINFO_TEXT, &CReportDlg::OnStnClickedReportdlg)
+END_MESSAGE_MAP()
+
+//==============================================================================
+/**
+ * Set the description of the crash.
+ * @param inErrorMessage the error message.
+ */
+//==============================================================================
+void CReportDlg::SetErrorMessage(CString inErrorMessage)
+{
+ m_ErrorMessage = inErrorMessage;
+}
+
+//==============================================================================
+/**
+ * Set the stack trace for the crash.
+ * @param inStackTrace the stack trace.
+ */
+//==============================================================================
+void CReportDlg::SetStackTrace(CString inStackTrace)
+{
+ m_StackTrace = inStackTrace;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CReportDlg message handlers
+
+void CReportDlg::OnSubmit()
+{
+ CWaitCursor theWaitCursor;
+
+ this->UpdateData(TRUE);
+
+ // Actual reporting functionality missing
+
+ this->EndDialog(TRUE);
+ exit(1);
+}
+
+void CReportDlg::OnCancel()
+{
+ this->EndDialog(FALSE);
+}
+
+BOOL CReportDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_Info = ::LoadResourceString(IDS_REPORTDLG_INFO).GetMulti();
+ m_DescHeader = ::LoadResourceString(IDS_REPORTDLG_DESCHEADER).GetMulti();
+ m_EmailHeader = ::LoadResourceString(IDS_REPORTDLG_EMAILHEADER).GetMulti();
+
+ CString theSysInfoText;
+ theSysInfoText = ""; //::LoadResourceString( IDS_REPORTDLG_SYSINFOHEADER ).GetMulti( );
+ // this is done this way, as i had problem changing the color of the text of the checkbox.
+ // it is now a seperate checkbox and a static text
+ // Made a workaround where the static text has notify flag on and would toggle the checkbox
+ // control on and off
+ // when clicked
+ m_SysInfoText = ::LoadResourceString(IDS_REPORTDLG_SYSINFOHEADER).GetMulti();
+
+ m_SendSysInfo.SetWindowText(theSysInfoText);
+ m_SendSysInfo.SetFont(&m_MediumFont2);
+ m_SendSysInfo.SetCheck(BST_CHECKED);
+
+ m_Brush.CreateSolidBrush(m_Color_Background);
+ GetDlgItem(IDC_REPORTDLG_INFO)->SetFont(&m_MediumFont2);
+ GetDlgItem(IDC_REPORTDLG_DESCHEADER)->SetFont(&m_MediumFont2);
+ GetDlgItem(IDC_REPORTDLG_EMAILADDR)->SetFont(&m_MediumFont2);
+ GetDlgItem(IDC_REPORTDLG_EMAILHEADER)->SetFont(&m_MediumFont2);
+ GetDlgItem(IDC_REPORTDLG__SYSINFO_TEXT)->SetFont(&m_MediumFont2);
+
+ this->UpdateData(FALSE);
+
+ return TRUE;
+}
+
+HBRUSH CReportDlg::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor)
+{
+ Q_UNUSED(nCtlColor);
+
+ int theCtrlID = pWnd->GetDlgCtrlID();
+ if (theCtrlID == IDSUBMIT || theCtrlID == IDCANCEL || theCtrlID == IDC_REPORTDLG_SEPERATOR
+ || theCtrlID == IDC_REPORTDLG_SYSINFO || theCtrlID == IDC_REPORTDLG__SYSINFO_TEXT
+ || theCtrlID == IDC_REPORTDLG_INFO || theCtrlID == IDC_REPORTDLG_DESCHEADER
+ || theCtrlID == IDC_REPORTDLG_EMAILHEADER) {
+ pDC->SetBkMode(TRANSPARENT); // for area just behind the text
+ pDC->SetTextColor(m_Color_Gray);
+ } else if (theCtrlID == IDC_REPORTDLG_DESC || theCtrlID == IDC_REPORTDLG_EMAILADDR) {
+ pDC->SetBkColor(m_Color_Background);
+ pDC->SetBkMode(OPAQUE); // for area just behind the text
+ pDC->SetTextColor(m_Color_Text);
+ }
+
+ return m_Brush;
+}
+
+BOOL CReportDlg::OnEraseBkgnd(CDC *pDC)
+{
+ CRect theClientRect;
+ GetClientRect(&theClientRect);
+ pDC->FillSolidRect(theClientRect, m_Color_Background);
+
+ return TRUE;
+}
+
+void CReportDlg::OnStnClickedReportdlg()
+{
+ m_SendSysInfo.SetCheck(!m_SendSysInfo.GetCheck());
+}
diff --git a/src/Authoring/Studio/_Win/UI/ReportDlg.h b/src/Authoring/Studio/_Win/UI/ReportDlg.h
new file mode 100644
index 00000000..c54743da
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ReportDlg.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#if !defined(AFX_REPORTDLG_H__B8564DEF_2599_4419_9E15_4AF38BE7066C__INCLUDED_)
+#define AFX_REPORTDLG_H__B8564DEF_2599_4419_9E15_4AF38BE7066C__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// ReportDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CReportDlg dialog
+
+class CReportDlg : public CDialog
+{
+ // Construction
+public:
+ CReportDlg(CWnd *pParent = nullptr); // standard constructor
+
+ COLORREF m_Color_Background;
+ COLORREF m_Color_Text;
+ COLORREF m_Color_Gray;
+ COLORREF m_Color_Dark;
+ CBrush m_Brush;
+ CFont m_MediumFont2;
+
+ // Dialog Data
+ //{{AFX_DATA(CReportDlg)
+ enum { IDD = IDD_REPORTDLG };
+ CButton m_SendSysInfo;
+ CEdit m_Description;
+ CString m_Info;
+ CString m_DescHeader;
+ CString m_EmailAddress;
+ CString m_EmailHeader;
+ //}}AFX_DATA
+
+ void SetErrorMessage(CString inErrorMessage);
+ void SetStackTrace(CString inStackTrace);
+
+ // Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CReportDlg)
+protected:
+ virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+ // Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CReportDlg)
+ afx_msg void OnSubmit();
+ virtual void OnCancel();
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+ CString m_ErrorMessage;
+ CString m_StackTrace;
+
+public:
+ afx_msg HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor);
+ afx_msg BOOL OnEraseBkgnd(CDC *pDC);
+ CString m_SysInfoText;
+ // afx_msg void OnStnClickedReportdlg();
+ afx_msg void OnStnClickedReportdlg();
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_REPORTDLG_H__B8564DEF_2599_4419_9E15_4AF38BE7066C__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.cpp b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.cpp
new file mode 100644
index 00000000..2eaa293a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "stdafx.h"
+#include "ResetKeyframeValuesDlg.h"
+#include ".\resetkeyframevaluesdlg.h"
+
+IMPLEMENT_DYNAMIC(CResetKeyframeValuesDlg, CDialog)
+CResetKeyframeValuesDlg::CResetKeyframeValuesDlg(CWnd *pParent /*=nullptr*/)
+ : CDialog(CResetKeyframeValuesDlg::IDD, pParent)
+{
+}
+
+CResetKeyframeValuesDlg::~CResetKeyframeValuesDlg()
+{
+}
+
+void CResetKeyframeValuesDlg::DoDataExchange(CDataExchange *pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_RESETKEYFRAMEVALUES_DLG_ICON, m_WarningIcon);
+ DDX_Control(pDX, IDCANCEL, m_CancelButton);
+}
+
+BEGIN_MESSAGE_MAP(CResetKeyframeValuesDlg, CDialog)
+END_MESSAGE_MAP()
+
+BOOL CResetKeyframeValuesDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_WarningIcon.SetIcon(::AfxGetApp()->LoadStandardIcon(IDI_WARNING));
+ m_CancelButton.SetButtonStyle(BS_DEFPUSHBUTTON);
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.h b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.h
new file mode 100644
index 00000000..d0a883d1
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Includes
+//==============================================================================
+#pragma once
+#include "Resource.h"
+#include "afxwin.h"
+
+class CResetKeyframeValuesDlg : public CDialog
+{
+ DECLARE_DYNAMIC(CResetKeyframeValuesDlg)
+
+public:
+ CResetKeyframeValuesDlg(CWnd *pParent = nullptr); // standard constructor
+ virtual ~CResetKeyframeValuesDlg();
+
+ // Dialog Data
+ enum { IDD = IDD_RESETKEYFRAMEVALUES_DLG };
+
+protected:
+ virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support
+
+ DECLARE_MESSAGE_MAP()
+ CStatic m_WarningIcon;
+
+public:
+ virtual BOOL OnInitDialog();
+ CButton m_CancelButton;
+};
diff --git a/src/Authoring/Studio/_Win/UI/SceneView.cpp b/src/Authoring/Studio/_Win/UI/SceneView.cpp
new file mode 100644
index 00000000..6fcbc6d0
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/SceneView.cpp
@@ -0,0 +1,861 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#ifdef _WIN32
+#pragma warning(disable : 4100) // unreferenced formal parameter
+#endif
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICOptions.h"
+#include "SceneView.h"
+//#include "InterpolationDlg.h"
+#include "MainFrm.h"
+#include "StudioProjectSettings.h"
+#include "StudioInstance.h"
+#include "StudioPreferences.h"
+#include "HotKeys.h"
+#include "StudioApp.h"
+#include "Doc.h"
+#include "Dispatch.h"
+#include "MouseCursor.h"
+#include "ResourceCache.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "WndControl.h"
+#endif
+#include "Core.h"
+#include "UICDMStudioSystem.h"
+#include "IStudioRenderer.h"
+#include "ClientDataModelBridge.h"
+
+#include <QKeyEvent>
+#include <QScrollBar>
+#include <QSettings>
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+
+CSceneView::CSceneView(CStudioApp *inStudioApp, QWidget *parent)
+ : QWidget(parent)
+{
+ Q_UNUSED(inStudioApp)
+ m_PreviousToolMode = g_StudioApp.GetToolMode();
+ m_PreviousSelectMode = g_StudioApp.GetSelectMode();
+
+ m_PlayerContainerWnd = new CPlayerContainerWnd(this);
+ connect(m_PlayerContainerWnd, &CPlayerContainerWnd::toolChanged, this, &CSceneView::toolChanged);
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Create the player container window
+ CPt theSize = CStudioPreferences::GetDefaultClientSize();
+
+ // Note that creating with WS_CLIPCHILDREN prevents flickering when SceneView is being
+ // resized.
+ m_PlayerContainerWnd->CreateEx(0, AfxRegisterWndClass(0, LoadCursor(NULL, IDC_ARROW),
+ (HBRUSH)GetStockObject(BLACK_BRUSH)),
+ L"player_container_wnd",
+ WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+ CRect(0, 0, theSize.x, theSize.y), this, 1000);
+#endif
+
+ m_PlayerWnd = new CPlayerWnd(m_PlayerContainerWnd);
+ connect(m_PlayerWnd, &CPlayerWnd::dropReceived, this, &CSceneView::onDropReceived);
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+ // Create the player frame child window
+ m_PlayerWnd.Create(AfxRegisterWndClass(0, LoadCursor(NULL, IDC_ARROW),
+ (HBRUSH)GetStockObject(WHITE_BRUSH)),
+ L"player_wnd", WS_CHILD | WS_VISIBLE, CRect(0, 0, theSize.x, theSize.y),
+ m_PlayerContainerWnd, 1001);
+#endif
+ m_PlayerContainerWnd->SetPlayerWnd(m_PlayerWnd);
+
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+}
+
+CSceneView::CSceneView()
+{
+ m_PreviousToolMode = g_StudioApp.GetToolMode();
+ m_PreviousSelectMode = g_StudioApp.GetSelectMode();
+}
+
+void CSceneView::onDropReceived()
+{
+ setFocus();
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+CSceneView::~CSceneView()
+{
+ CDispatch *theDispatch = g_StudioApp.GetCore()->GetDispatch();
+ // Stop listening for selection change events
+ theDispatch->RemoveSelectedNodePropChangeListener(this);
+ theDispatch->RemoveClientPlayChangeListener(this);
+#ifdef INCLUDE_EDIT_CAMERA
+ theDispatch->RemoveEditCameraChangeListener(this);
+#endif
+}
+
+QSize CSceneView::sizeHint() const
+{
+ CPt theSize = CStudioPreferences::GetDefaultClientSize();
+ return QSize(theSize.x, theSize.y);
+}
+
+//====================================================m==========================
+/**
+ * Called by the framework after the view is first attached
+ * to the document, but before the view is initially displayed.
+ * Notifies the Main Frame that the palettes need to be shown, and destroys the
+ * splash screen.
+ */
+void CSceneView::showEvent(QShowEvent *event)
+{
+ QWidget::showEvent(event);
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+ // Modify the style for WS_CLIPCHILDREN
+ ModifyStyle(0, WS_CLIPCHILDREN);
+#endif
+
+ m_PlayerContainerWnd->RecenterClient();
+
+ // Set the scroll information.
+ m_PlayerContainerWnd->SetScrollRanges();
+
+ // Create the cursors
+ m_ArrowCursor = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ARROW);
+ m_CursorGroupMove = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_GROUP_MOVE);
+ m_CursorGroupRotate =
+ CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_GROUP_ROTATE);
+ m_CursorGroupScale = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_GROUP_SCALE);
+ m_CursorItemMove = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ITEM_MOVE);
+ m_CursorItemRotate = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ITEM_ROTATE);
+ m_CursorItemScale = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ITEM_SCALE);
+ m_CursorEditCameraPan =
+ CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_EDIT_CAMERA_PAN);
+ m_CursorEditCameraRotate =
+ CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_EDIT_CAMERA_ROTATE);
+ m_CursorEditCameraZoom =
+ CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_EDIT_CAMERA_ZOOM);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ g_StudioApp.GetCore()->GetDispatch()->AddEditCameraChangeListener(this);
+#endif
+
+ // Set the default cursor
+ OnSetCursor();
+}
+
+void CSceneView::keyPressEvent(QKeyEvent *event)
+{
+ /*switch (event->key())
+ {
+ case Qt::Key_Control:
+ case Qt::Key_Alt:
+ case Qt::Key_Shift:
+ case Qt::Key_Meta:
+ HandleModifierDown(event->key(), event->isAutoRepeat() ? 2 : 1, event->modifiers());
+ break;
+ default:
+ break;
+ }*/
+}
+
+//==============================================================================
+/**
+ * OnToolGroupSelection: Called when the Group Selection button is pressed.
+ * Sets the current tool mode and changes the cursor.
+ */
+void CSceneView::OnToolGroupSelection()
+{
+ m_PreviousSelectMode = g_StudioApp.GetSelectMode();
+ g_StudioApp.SetSelectMode(STUDIO_SELECTMODE_GROUP);
+ OnSetCursor();
+ Q_EMIT toolChanged();
+}
+
+//==============================================================================
+/**
+ * OnToolItemSelection: Called when the Item Selection button is pressed.
+ * Sets the current tool mode and changes the cursor.
+ */
+void CSceneView::OnToolItemSelection()
+{
+ m_PreviousSelectMode = g_StudioApp.GetSelectMode();
+ g_StudioApp.SetSelectMode(STUDIO_SELECTMODE_ENTITY);
+ OnSetCursor();
+ Q_EMIT toolChanged();
+}
+
+
+//==============================================================================
+/**
+ * SetViewCursor: Sets the cursor for the view according to the current Client Tool.
+ *
+ * Changes the cursor depending on the current tool mode. Each time the Tool mode
+ * changes, you should call this function. If you add extra tool modes, you
+ * will need to adjust this function.
+ */
+void CSceneView::SetViewCursor()
+{
+ long theCurrentToolSettings = g_StudioApp.GetToolMode();
+ long theCurrentSelectSettings = g_StudioApp.GetSelectMode();
+
+ // See what tool mode we are in
+ switch (theCurrentToolSettings) {
+ case STUDIO_TOOLMODE_MOVE:
+ switch (theCurrentSelectSettings) {
+ case STUDIO_SELECTMODE_ENTITY:
+ m_PlayerWnd->setCursor(m_CursorItemMove);
+ break;
+ case STUDIO_SELECTMODE_GROUP:
+ m_PlayerWnd->setCursor(m_CursorGroupMove);
+ break;
+ // Default - shouldn't happen
+ default:
+ m_PlayerWnd->setCursor(m_CursorItemMove);
+ break;
+ }
+ break;
+
+ case STUDIO_TOOLMODE_ROTATE:
+ switch (theCurrentSelectSettings) {
+ case STUDIO_SELECTMODE_ENTITY:
+ m_PlayerWnd->setCursor(m_CursorItemRotate);
+ break;
+ case STUDIO_SELECTMODE_GROUP:
+ m_PlayerWnd->setCursor(m_CursorGroupRotate);
+ break;
+ // Default - shouldn't happen
+ default:
+ m_PlayerWnd->setCursor(m_CursorItemRotate);
+ break;
+ }
+ break;
+
+ case STUDIO_TOOLMODE_SCALE:
+ switch (theCurrentSelectSettings) {
+ case STUDIO_SELECTMODE_ENTITY:
+ m_PlayerWnd->setCursor(m_CursorItemScale);
+ break;
+ case STUDIO_SELECTMODE_GROUP:
+ m_PlayerWnd->setCursor(m_CursorGroupScale);
+ break;
+ // Default - shouldn't happen
+ default:
+ m_PlayerWnd->setCursor(m_CursorItemScale);
+ break;
+ }
+ break;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ case STUDIO_TOOLMODE_CAMERA_PAN:
+ m_PlayerWnd->setCursor(m_CursorEditCameraPan);
+ break;
+
+ case STUDIO_TOOLMODE_CAMERA_ZOOM:
+ m_PlayerWnd->setCursor(m_CursorEditCameraZoom);
+ break;
+
+ case STUDIO_TOOLMODE_CAMERA_ROTATE:
+ m_PlayerWnd->setCursor(m_CursorEditCameraRotate);
+ break;
+#endif
+ // Default - shouldn't happen
+ default:
+ m_PlayerWnd->setCursor(m_CursorItemMove);
+ break;
+ }
+}
+
+//==============================================================================
+/**
+ * RecalcMatte: Recalculates the matte around the Client based on the settings.
+ *
+ * This will recalculate the matting around the Client based on the Client's
+ * current size. If the Client is a "Fit To Window" mode, then the matte region
+ * is cleared.
+ */
+//==============================================================================
+void CSceneView::RecalcMatte()
+{
+ long theXOffset = 0;
+ long theYOffset = 0;
+ QRect theClientRect = rect();
+
+ // Adjust the client area based if rulers are visible
+ if (m_PlayerContainerWnd) {
+ m_PlayerContainerWnd->setGeometry(theXOffset, theYOffset,
+ theClientRect.width() - theXOffset,
+ theClientRect.height() - theYOffset);
+
+ // Recenter the Client rect
+ m_PlayerContainerWnd->RecenterClient();
+ }
+}
+
+//==============================================================================
+/**
+ * PtInClientRect: Returns true if the point lies in the client rect, false otherwise.
+ *
+ * @param inPoint The point to check.
+ */
+//==============================================================================
+bool CSceneView::PtInClientRect(const QPoint& inPoint)
+{
+ return m_PlayerContainerWnd && m_PlayerContainerWnd->geometry().contains(inPoint);
+}
+
+//==============================================================================
+/**
+ * HandleModifierDown: Called when a modifier key (ctrl or alt) is pressed and held.
+ *
+ * Changes tool modes and saves the previous mode.
+ *
+ * @param inChar Contains the character code value of the key.
+ * @param inRepCnt Contains the repeat count, the number of times the keystroke
+ *is repeated when user holds down the key.
+ * @param inFlags Contains the scan code, key-transition code, previous
+ *key state, and context code.
+ */
+//==============================================================================
+bool CSceneView::HandleModifierDown(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers)
+{
+ bool theHandledFlag = false;
+
+ UNREFERENCED_PARAMETER(inRepCnt);
+
+ // Get the position of the mouse and the rectangle containing the scene view
+ QPoint theCursorPosition = mapFromGlobal(QCursor::pos());
+ QRect theWindowRect = rect();
+
+ // If we are currently dragging an object or the cursor is over the scene
+ if (((theWindowRect.contains(theCursorPosition))
+ || (m_PlayerContainerWnd && m_PlayerContainerWnd->IsMouseDown()))) {
+ bool theCtrlKeyIsDown = modifiers & Qt::ControlModifier;
+ bool theAltKeyIsDown = modifiers & Qt::AltModifier;
+
+ // If the control key is being pressed and the Alt key is not down
+ if ((inChar == Qt::Key_Control) && (!theAltKeyIsDown)) {
+ // If this is the first press, toggle tool modes
+ m_RegisteredKeyDown = true;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ if (m_PlayerContainerWnd->IsMiddleMouseDown() && !IsDeploymentView()) {
+ // Do nothing, do not let it switch to other tool when middle mouse is down
+ } else
+#endif
+ {
+ // See what tool mode we are in and change modes accordingly
+ SetToolOnCtrl();
+ theHandledFlag = true;
+ }
+ }
+ // If the alt key is being pressed and the control key is not down
+ else if ((inChar == Qt::Key_Alt) && (!theCtrlKeyIsDown)) {
+ m_RegisteredKeyDown = true;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ if (m_PlayerContainerWnd->IsMiddleMouseDown() && !IsDeploymentView()) {
+ // press Alt-Scroll Wheel Click
+ // Do Camera Rotate if we are in 3D Camera
+ if (g_StudioApp.GetRenderer().DoesEditCameraSupportRotation(
+ g_StudioApp.GetRenderer().GetEditCamera())) {
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+ theHandledFlag = true;
+ }
+ } else
+#endif
+ {
+ // See what tool mode we are in and change modes accordingly
+ SetToolOnAlt();
+ theHandledFlag = true;
+ }
+ }
+ OnSetCursor();
+ Q_EMIT toolChanged();
+ }
+
+ return theHandledFlag;
+}
+
+//==============================================================================
+/**
+ * HandleModifierUp: Handles the release of a modifier key (ctrl or alt).
+ *
+ * Changes tool modes back to the original tool mode.
+ *
+ * @param inChar Contains the character code value of the key.
+ * @param inRepCnt Contains the repeat count, the number of times the keystroke is
+ *repeated when user holds down the key.
+ * @param inFlags Contains the scan code, key-transition code, previous key
+ *state, and context code.
+ */
+//==============================================================================
+bool CSceneView::HandleModifierUp(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers)
+{
+ UNREFERENCED_PARAMETER(inRepCnt);
+
+ bool theHandledFlag = false;
+
+ // Get the position of the mouse and the rectangle containing the scene view
+ QPoint theCursorPosition = mapFromGlobal(QCursor::pos());
+ QRect theWindowRect = rect();
+
+ // If we are currently dragging an object or the cursor is over the scene
+ if (((theWindowRect.contains(theCursorPosition))
+ || (m_PlayerContainerWnd && m_PlayerContainerWnd->IsMouseDown()))) {
+ bool theCtrlKeyIsDown = modifiers & Qt::ControlModifier;
+ bool theAltKeyIsDown = modifiers & Qt::AltModifier;
+
+ // If the control key or alt key is released (and the opposite key is not down) revert back
+ // to the original tool mode
+ if (((inChar == Qt::Key_Control) && (!theAltKeyIsDown))
+ || ((inChar == Qt::Key_Alt) && (!theCtrlKeyIsDown))) {
+#ifdef INCLUDE_EDIT_CAMERA
+ if (m_PlayerContainerWnd->IsMiddleMouseDown())
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ else
+#endif
+ {
+ RestorePreviousTool();
+ }
+
+ OnSetCursor();
+ Q_EMIT toolChanged();
+
+ theHandledFlag = true;
+ }
+ // m_RegisteredKeyDown = false;
+ }
+
+ return theHandledFlag;
+}
+
+//==============================================================================
+/**
+ * resizeEvent: Handles the WM_SIZE message
+ *
+ * Recenters the Client and recaluclates the matte when a resize message is
+ * generated.
+ *
+ * @param nType Specifies the type of resizing requested.
+ * @param cx Specifies the new width of the client area.
+ * @param cy Specifies the new height of the client area.
+ */
+//==============================================================================
+void CSceneView::resizeEvent(QResizeEvent* event)
+{
+ QWidget::resizeEvent(event);
+ if (m_PlayerContainerWnd) {
+ RecalcMatte();
+ SetPlayerWndPosition();
+ g_StudioApp.GetCore()->GetDoc( )->GetSceneGraph()->RequestRender();
+ }
+}
+
+//==============================================================================
+/**
+ * SetPlayerWndPosition: Sets the position of the child player window
+ *
+ * Called when the view is scrolled to position the child player window
+ *
+ */
+//==============================================================================
+void CSceneView::SetPlayerWndPosition()
+{
+ // Move the child player window to coincide with the scrollbars
+ if (m_PlayerContainerWnd) {
+ long theLeft, theTop;
+ // Retrieve the left and top edge of the presentation currently in view
+ m_PlayerContainerWnd->SetPlayerWndPosition(theLeft, theTop);
+
+ m_PlayerContainerWnd->update();
+ }
+}
+
+//==============================================================================
+/**
+ * GetPlayerHwnd: Gets the window handle for the player object.
+ *
+ * @return <HWND> Window handle for the player window
+ */
+//==============================================================================
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+
+HWND CSceneView::GetPlayerHwnd()
+{
+ HWND thePlayerWnd;
+
+ thePlayerWnd = this->GetSafeHwnd();
+
+ if (IsWindow(m_PlayerWnd.GetSafeHwnd()))
+ thePlayerWnd = m_PlayerWnd.GetSafeHwnd();
+
+ return thePlayerWnd;
+}
+#endif
+//==============================================================================
+/**
+ * SetRegisteredKey: Sets the staus to true or false
+ *
+ * If we've already processesed an alt or tab, then set the flag
+ */
+//==============================================================================
+void CSceneView::SetRegisteredKey(bool inStatus)
+{
+ m_RegisteredKeyDown = inStatus;
+}
+
+//==============================================================================
+/**
+ * GetKeyStatus: get the staus
+ *
+ * check to see if the flag is true or false
+ */
+//==============================================================================
+bool CSceneView::GetKeyStatus()
+{
+ return m_RegisteredKeyDown;
+}
+
+//=============================================================================
+/**
+ * Register all the events for hotkeys that are active for the entire application.
+ * Hotkeys for the entire application are ones that are not view specific in
+ * scope.
+ *
+ * @param inShortcutHandler the global shortcut handler.
+ */
+//=============================================================================
+void CSceneView::RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler)
+{
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::OnToolGroupSelection), 0, Qt::Key_A);
+ inShortcutHandler->RegisterKeyEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::OnToolItemSelection), 0, Qt::Key_V);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierDown),
+ Qt::ControlModifier, Qt::Key_Control);
+ inShortcutHandler->RegisterKeyDownEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierDown),
+ Qt::AltModifier, Qt::Key_Alt);
+ inShortcutHandler->RegisterKeyUpEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierUp), 0,
+ Qt::Key_Control);
+ inShortcutHandler->RegisterKeyUpEvent(
+ new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierUp), 0,
+ Qt::Key_Alt);
+}
+
+//==============================================================================
+/**
+ * OnSetCursor: Handles the WM_SETCURSOR Windows message.
+ *
+ * Changes the cursor depending on the current tool mode.
+ *
+ * @param inWnd Specifies a pointer to the window that contains the cursor.
+ * @param inHitTest Specifies the hit-test area code. The hit test determines the cursor�s
+ *location.
+ * @param inMessage Specifies the mouse message number.
+ *
+ * @return true if the cursor was set
+ */
+void CSceneView::OnSetCursor()
+{
+ SetViewCursor();
+}
+
+//==============================================================================
+/**
+ * Called when the tool mode changes, scene view maintains its own mode so it can
+ * return to that mode when modifiers are pressed
+ * @param inMode the mode to which to change
+ */
+void CSceneView::SetToolMode(long inMode)
+{
+ m_PreviousToolMode = inMode;
+ SetViewCursor();
+}
+
+//==============================================================================
+/**
+ * Resets its scroll ranges and recenters client in the window. This is called when
+ * an outside source needs to tell the scene view that size ranges have changed such
+ * as the preferences telling the sceneview that the size changed.
+ */
+void CSceneView::RecheckSizingMode()
+{
+ if (m_PlayerContainerWnd) {
+ m_PlayerContainerWnd->SetScrollRanges();
+ }
+}
+
+//=============================================================================
+/**
+ * Called a selected node property has changed.
+ * @param inPropertyName name of the property changed
+ */
+void CSceneView::OnPropValueChanged(const Q3DStudio::CString &inPropertyName)
+{
+}
+
+//=============================================================================
+/**
+ * Called a selected node property has its property changed via a mouse drag
+ * @param inConstrainXAxis true if dragging is constrained along the X-Axis
+ * @param inConstrainYAxis true if dragging is constrained along the Y-Axis
+ */
+void CSceneView::OnMouseDragged(bool inConstrainXAxis, bool inConstrainYAxis)
+{
+ // If not constraining to Y-Axis, snap horizontally
+ // If not constraining to X-Axis, snap vertically
+ // true to update tranform, as this is called from a mouse drag and the global transform may be
+ // outdated.
+ // false to not update the scene, since this is a result of a mouse drag which is already doing
+ // the updating
+}
+
+//==========================================================================
+/**
+ * Called when the presentation time changes.
+ * When animating an object, the markers must be updated with the selected object
+ */
+void CSceneView::OnTimeChanged(long inTime)
+{
+ UNREFERENCED_PARAMETER(inTime);
+}
+
+//==============================================================================
+/**
+ * Restore to the previous tool mode. This is called when the modifier is released
+ */
+//==============================================================================
+void CSceneView::RestorePreviousTool()
+{
+ // What was the original tool mode?
+ switch (m_PreviousToolMode) {
+ case STUDIO_TOOLMODE_MOVE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE);
+ break;
+
+ case STUDIO_TOOLMODE_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_ROTATE);
+ break;
+
+ case STUDIO_TOOLMODE_SCALE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_SCALE);
+ break;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ case STUDIO_TOOLMODE_CAMERA_PAN:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ break;
+
+ case STUDIO_TOOLMODE_CAMERA_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+ break;
+
+ case STUDIO_TOOLMODE_CAMERA_ZOOM:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ZOOM);
+ break;
+#endif
+ }
+}
+
+//==============================================================================
+/**
+ * Change the tool when the Ctrl Key is pressed
+ */
+//==============================================================================
+void CSceneView::SetToolOnCtrl()
+{
+ switch (m_PreviousToolMode) {
+ // If we are in move mode, switch to rotate
+ case STUDIO_TOOLMODE_MOVE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_ROTATE);
+ break;
+
+ // If we are in rotate mode, switch to move
+ case STUDIO_TOOLMODE_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE);
+ break;
+
+ // If we are in scale mode, switch to move
+ case STUDIO_TOOLMODE_SCALE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE);
+ break;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ // If we are in camera pan mode, switch to camera orbit
+ case STUDIO_TOOLMODE_CAMERA_PAN:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+ break;
+
+ // If we are in camera orbit mode, switch to camera pan
+ case STUDIO_TOOLMODE_CAMERA_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ break;
+
+ // If we are in camera zoom mode, switch to camera pan
+ case STUDIO_TOOLMODE_CAMERA_ZOOM:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN);
+ break;
+#endif
+ }
+}
+
+//==============================================================================
+/**
+ * Change the tool when the Alt Key is pressed
+ */
+//==============================================================================
+void CSceneView::SetToolOnAlt()
+{
+ switch (m_PreviousToolMode) {
+ // If we are in move mode, switch to rotate
+ case STUDIO_TOOLMODE_MOVE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_SCALE);
+ break;
+
+ // If we are in rotate mode, switch to move
+ case STUDIO_TOOLMODE_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_SCALE);
+ break;
+
+ // If we are in scale mode, switch to move
+ case STUDIO_TOOLMODE_SCALE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_ROTATE);
+ break;
+
+#ifdef INCLUDE_EDIT_CAMERA
+ // If we are in camera pan mode, switch to camera zoom
+ case STUDIO_TOOLMODE_CAMERA_PAN:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ZOOM);
+ break;
+
+ // If we are in camera orbit mode, switch to camera zoom
+ case STUDIO_TOOLMODE_CAMERA_ROTATE:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ZOOM);
+ break;
+
+ // If we are in camera zoom mode, switch to camera orbit
+ case STUDIO_TOOLMODE_CAMERA_ZOOM:
+ g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE);
+ break;
+#endif
+ }
+}
+
+//==============================================================================
+/**
+ * Redirect to PlayerContainerWnd to check whether we are in deployment view mode.
+ * @return true if is in deployment view mode, else false
+ */
+bool CSceneView::IsDeploymentView()
+{
+ // default mode is SCENE_VIEW so if playercontainerwnd does not exist ( should only happen on
+ // startup ),
+ // it is deployment view
+ bool theStatus = true;
+ if (m_PlayerContainerWnd)
+ theStatus = m_PlayerContainerWnd->IsDeploymentView();
+
+ return theStatus;
+}
+
+//==============================================================================
+/**
+ * Redirect to PlayerContainerWnd to set the view mode of the current scene view,
+ * whether we are in editing mode or deployment mode. For editing mode, we want to
+ * use the full scene area without any matte area.
+ * @param inViewMode the view mode of this scene
+ */
+void CSceneView::SetViewMode(CPlayerContainerWnd::EViewMode inViewMode)
+{
+ if (m_PlayerContainerWnd) {
+ m_PlayerContainerWnd->SetViewMode(inViewMode);
+ }
+}
+
+//==============================================================================
+/**
+ * When the active camera is changed, the display string needs to be changed. Hence
+ * find which entry is the one which is modified and update with the new string
+ * @param inCamera the camera that has been modified
+ */
+void CSceneView::OnEditCameraChanged()
+{
+ // reset any scrolling and recalculate the window position.
+ if (m_PlayerContainerWnd) {
+ m_PlayerContainerWnd->SetScrollRanges();
+ RecalcMatte();
+ SetPlayerWndPosition();
+ }
+
+ // update the view mode accordingly
+ SetViewMode(g_StudioApp.GetRenderer().GetEditCamera() >= 0 ? CPlayerContainerWnd::VIEW_EDIT
+ : CPlayerContainerWnd::VIEW_SCENE);
+ // redraw the scene so that markers can be calculated correctly
+ // g_StudioApp.GetCore()->GetDoc( )->UpdateClientScene( false );
+ m_PlayerWnd->update();
+}
+
+//==============================================================================
+/**
+ * When the active camera is changed, the display string needs to be changed. Hence
+ * find which entry is the one which is modified and update with the new string
+ * @param inCamera the camera that has been modified
+ */
+void CSceneView::OnEditCamerasTransformed()
+{
+}
+
+void CSceneView::OnAuthorZoomChanged()
+{
+ OnEditCameraChanged();
+}
+
+void CSceneView::OnRulerGuideToggled()
+{
+ m_PlayerContainerWnd->OnRulerGuideToggled();
+}
diff --git a/src/Authoring/Studio/_Win/UI/SceneView.h b/src/Authoring/Studio/_Win/UI/SceneView.h
new file mode 100644
index 00000000..12a58c6a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/SceneView.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_SCENE_VIEW_H
+#define INCLUDED_SCENE_VIEW_H 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <QWidget>
+#include <QCursor>
+
+#include "EditorPane.h"
+#include "PlayerWnd.h"
+#include "PlayerContainerWnd.h"
+#include "DispatchListeners.h"
+
+class CStudioApp;
+class CHotKeys;
+class CMouseCursor;
+class CWndControl;
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+// Class CSceneView
+//==============================================================================
+
+//==============================================================================
+/**
+ * CSceneView: Scene View.
+ *
+ * Provides the view of the scene and displays the 3D Client window.
+ */
+//==============================================================================
+class CSceneView : public QWidget,
+ public CEditorPane,
+ public CSelectedNodePropChangeListener,
+ public CClientPlayChangeListener,
+ public CEditCameraChangeListener
+{
+ Q_OBJECT
+ //==========================================================================
+ // Protected Properties
+ //==========================================================================
+protected:
+ bool m_FitClientToWindow = false; ///< True if user selected fit to window in prefrences
+ bool m_RegisteredKeyDown = false; ///< True if a key is down
+ CPlayerContainerWnd *m_PlayerContainerWnd = nullptr; ///< first-level child
+ CPlayerWnd *m_PlayerWnd = nullptr; ///< second-level child (grandchild)
+ QCursor m_ArrowCursor; ///< A pointer to the current cursor (changes according to mode)
+ QCursor m_CursorGroupMove; ///< The move group cursor
+ QCursor m_CursorGroupRotate; ///< The rotate group cursor
+ QCursor m_CursorGroupScale; ///< The scale group cursor
+ QCursor m_CursorItemMove; ///< The move item cursor
+ QCursor m_CursorItemRotate; ///< The rotate item cursor
+ QCursor m_CursorItemScale; ///< The scale item cursor
+ QCursor m_CursorEditCameraPan; ///< The edit camera pan cursor
+ QCursor m_CursorEditCameraRotate; ///< The edit camera rotate cursor
+ QCursor m_CursorEditCameraZoom; ///< The edit camera zoom cursor
+
+ long m_PreviousToolMode; ///< The previous tool mode (used when toggling with hotkeys to switch
+ ///back to previous mode on release)
+ long m_PreviousSelectMode; ///< The previous select mode
+
+ //==========================================================================
+ // Protected Methods
+ //==========================================================================
+protected: // create from serialization only
+
+ //==========================================================================
+ // Public Methods
+ //==========================================================================
+public:
+ CSceneView(CStudioApp *inStudioApp, QWidget *parent = nullptr);
+ CSceneView(); // used for serialization only!
+ virtual ~CSceneView();
+
+ bool HandleModifierUp(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers);
+ bool HandleModifierDown(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers);
+ bool PtInClientRect(const QPoint& inPoint);
+ void SetViewCursor();
+ void SetToolMode(long inMode);
+ void RecheckSizingMode();
+
+ void SetRegisteredKey(bool inStatus);
+ void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler);
+ bool GetKeyStatus();
+
+ void SetPlayerWndPosition();
+
+ // redirect to/from PlayerContainerWnd
+ bool IsDeploymentView();
+ void SetViewMode(CPlayerContainerWnd::EViewMode inViewMode);
+
+ // Tool helper methods
+ void RestorePreviousTool();
+ void SetToolOnCtrl();
+ void SetToolOnAlt();
+
+ void OnRulerGuideToggled();
+
+ // CSelectedNodePropChangeListener
+ void OnPropValueChanged(const Q3DStudio::CString &inPropertyName) override;
+ void OnMouseDragged(bool inConstrainXAxis, bool inConstrainYAxis) override;
+
+ // CClientPlayChangeListener
+ void OnTimeChanged(long inTime) override;
+
+ // CEditCameraChangeListener
+
+ void OnEditCameraChanged() override;
+ void OnEditCamerasTransformed() override;
+ void OnAuthorZoomChanged() override;
+
+ QSize sizeHint() const override;
+
+ void OnToolGroupSelection();
+ void OnToolItemSelection();
+public:
+
+ void resizeEvent(QResizeEvent *event) override;
+
+Q_SIGNALS:
+ void toolChanged();
+
+protected:
+ void RecalcMatte();
+
+ // Generated message map functions
+protected:
+ void OnSetCursor();
+ void showEvent(QShowEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+private:
+ void onDropReceived();
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // INCLUDED_SCENE_VIEW_H
diff --git a/src/Authoring/Studio/_Win/UI/StartupDlg.cpp b/src/Authoring/Studio/_Win/UI/StartupDlg.cpp
new file mode 100644
index 00000000..286d94e3
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StartupDlg.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "StudioDefs.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "StartupDlg.h"
+
+#include "StudioPreferences.h"
+#include "ui_StartupDlg.h"
+
+#include <QtCore/qfileinfo.h>
+#include <QtGui/qpalette.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qdir.h>
+
+// CStartupDlg dialog
+
+CStartupDlg::CStartupDlg(QWidget *pParent)
+ : QDialog(pParent, Qt::MSWindowsFixedSizeDialogHint | Qt::FramelessWindowHint)
+ , m_Choice(EStartupChoice_Invalid)
+ , m_RecentDocSelected("")
+ , m_ui(new Ui::StartupDlg)
+ , m_palette(nullptr)
+{
+ m_ui->setupUi(this);
+}
+
+CStartupDlg::~CStartupDlg()
+{
+ delete m_palette;
+}
+
+static QString GetFileTimeReadable(const CUICFile &inFile)
+{
+ QFileInfo finfo(inFile.GetAbsolutePath().toQString());
+ if (!finfo.exists())
+ return {};
+
+ return finfo.lastModified().toString("MM/dd/yyyy");
+}
+
+void CStartupDlg::showEvent(QShowEvent *ev)
+{
+ OnInitDialog();
+ QDialog::showEvent(ev);
+}
+
+void CStartupDlg::OnInitDialog()
+{
+ connect(m_ui->newDocument, &QPushButton::clicked, this, &CStartupDlg::OnNewDocClicked);
+ connect(m_ui->openDocument, &QPushButton::clicked, this, &CStartupDlg::OnOpenDocClicked);
+
+ // Load the product version
+ m_ProductVersionStr.Format(
+ ::LoadResourceString(IDS_UIC_STUDIO_VERSION),
+ static_cast<const wchar_t *>(CStudioPreferences::GetVersionString()));
+ m_ui->versionStr->setText(m_ProductVersionStr.toQString());
+
+ // Populate the recent document list
+ for (uint theIndex = 0; theIndex < RECENT_COUNT; ++theIndex) {
+ ClickableLabel *recent
+ = findChild<ClickableLabel *>(QStringLiteral("recent%1").arg(theIndex));
+ connect(recent, &ClickableLabel::clicked, this, &CStartupDlg::OnStnClickedStartupRecent);
+
+ recent->setProperty("recentIndex", theIndex);
+
+ if (m_RecentDocs.size() > theIndex) {
+ // Set the name
+ recent->setText(m_RecentDocs[theIndex].GetName().toQString());
+ // Set path and date to tooltip
+ QFileInfo thePath(m_RecentDocs[theIndex].GetAbsolutePath().toQString());
+ QString toolTip = thePath.absoluteDir().path();
+ toolTip.append(QStringLiteral("\n"));
+ toolTip.append(GetFileTimeReadable(m_RecentDocs[theIndex]));
+ recent->setToolTip(toolTip);
+ } else {
+ recent->hide();
+ }
+ }
+}
+
+void CStartupDlg::AddRecentItem(const CUICFile &inRecentItem)
+{
+ m_RecentDocs.push_back(inRecentItem);
+}
+
+CStartupDlg::EStartupChoice CStartupDlg::GetChoice()
+{
+ return m_Choice;
+}
+
+CUICFile CStartupDlg::GetRecentDoc() const
+{
+ return m_RecentDocSelected;
+}
+
+void CStartupDlg::OnNewDocClicked()
+{
+ m_Choice = EStartupChoice_NewDoc;
+ QDialog::accept();
+}
+
+void CStartupDlg::OnOpenDocClicked()
+{
+ m_Choice = EStartupChoice_OpenDoc;
+ QDialog::accept();
+}
+
+void CStartupDlg::OnStnClickedStartupRecent()
+{
+ const int index = sender()->property("recentIndex").toInt();
+ OpenRecent(index);
+}
+
+void CStartupDlg::OpenRecent(size_t inIndex)
+{
+ if (inIndex < m_RecentDocs.size()) {
+ m_RecentDocSelected = m_RecentDocs[inIndex];
+ m_Choice = EStartupChoice_OpenRecent;
+ QDialog::accept();
+ }
+}
+
+void CStartupDlg::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event)
+ if (m_palette)
+ return;
+
+ delete m_palette;
+ m_palette = new QPalette;
+ QPixmap pic = QPixmap(":/startup/open_dialog.png");
+ pic.setDevicePixelRatio(devicePixelRatio());
+ m_palette->setBrush(QPalette::Window, pic);
+ setPalette(*m_palette);
+ resize(pic.size());
+ setFixedSize(size());
+}
diff --git a/src/Authoring/Studio/_Win/UI/StartupDlg.h b/src/Authoring/Studio/_Win/UI/StartupDlg.h
new file mode 100644
index 00000000..6fbd0a2a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StartupDlg.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2006 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#ifndef INCLUDED_STARTUP_DLG
+#define INCLUDED_STARTUP_DLG 1
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <QDialog>
+
+#include "UICString.h"
+#include "UICFile.h"
+
+#ifdef QT_NAMESPACE
+using namespace QT_NAMESPACE;
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class StartupDlg;
+}
+QT_END_NAMESPACE
+
+//==============================================================================
+/**
+ * CGLVersionDlg: Dialog class for showing what user can do upon startup
+ */
+//==============================================================================
+class CStartupDlg : public QDialog
+{
+ Q_OBJECT
+public:
+ enum EStartupChoice {
+ EStartupChoice_Invalid = -1,
+ EStartupChoice_NewDoc,
+ EStartupChoice_OpenDoc,
+ EStartupChoice_OpenRecent,
+ EStartupChoice_Exit
+ };
+
+public:
+ CStartupDlg(QWidget *pParent = nullptr); // standard constructor
+ virtual ~CStartupDlg();
+
+protected:
+ const static int RECENT_COUNT = 5;
+
+ void paintEvent(QPaintEvent *event) override;
+ void showEvent(QShowEvent *) override;
+
+protected Q_SLOTS:
+ void OnNewDocClicked();
+ void OnOpenDocClicked();
+ void OnStnClickedStartupRecent();
+ void OpenRecent(size_t inIndex);
+
+private:
+ // Dialog background
+ QPalette *m_palette;
+
+ // Product version string
+ Q3DStudio::CString m_ProductVersionStr;
+
+ // Choice
+ EStartupChoice m_Choice = EStartupChoice_Invalid;
+
+ // Recent Docs
+ std::vector<CUICFile> m_RecentDocs;
+ CUICFile m_RecentDocSelected;
+
+public:
+ void OnInitDialog();
+ void AddRecentItem(const CUICFile &inRecentItem);
+ EStartupChoice GetChoice();
+ CUICFile GetRecentDoc() const;
+
+private:
+ QScopedPointer<Ui::StartupDlg> m_ui;
+};
+
+#endif // INCLUDED_STARTUP_DLG
diff --git a/src/Authoring/Studio/_Win/UI/StartupDlg.ui b/src/Authoring/Studio/_Win/UI/StartupDlg.ui
new file mode 100644
index 00000000..619c857a
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StartupDlg.ui
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StartupDlg</class>
+ <widget class="QDialog" name="StartupDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>442</width>
+ <height>650</height>
+ </rect>
+ </property>
+ <widget class="QLabel" name="recentDocLabel">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>250</y>
+ <width>411</width>
+ <height>29</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>RECENT FILES</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QWidget" name="verticalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>290</y>
+ <width>401</width>
+ <height>341</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="recentList">
+ <item>
+ <widget class="ClickableLabel" name="recent0">
+ <property name="text">
+ <string>Recent0.uip</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="docIndex" stdset="0">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ClickableLabel" name="recent1">
+ <property name="text">
+ <string>Recent1.uip</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="docIndex" stdset="0">
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ClickableLabel" name="recent2">
+ <property name="text">
+ <string>Recent2.uip</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="docIndex" stdset="0">
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ClickableLabel" name="recent3">
+ <property name="text">
+ <string>Recent3.uip</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="docIndex" stdset="0">
+ <number>3</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ClickableLabel" name="recent4">
+ <property name="text">
+ <string>Recent3.uip</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="docIndex" stdset="0">
+ <number>3</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="verticalLayoutWidget_2">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>130</y>
+ <width>161</width>
+ <height>101</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="buttons">
+ <item>
+ <widget class="QPushButton" name="newDocument">
+ <property name="text">
+ <string>Create Project...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../../MainFrm.qrc">
+ <normaloff>:/res/Toolbar-00.png</normaloff>:/res/Toolbar-00.png</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="openDocument">
+ <property name="text">
+ <string>Open Project...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../../MainFrm.qrc">
+ <normaloff>:/res/Toolbar-01.png</normaloff>:/res/Toolbar-01.png</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="versionStr">
+ <property name="geometry">
+ <rect>
+ <x>290</x>
+ <y>90</y>
+ <width>141</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Qt 3D Studio version string</string>
+ </property>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>ClickableLabel</class>
+ <extends>QLabel</extends>
+ <header>ClickableLabel.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="../../MainFrm.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.cpp b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.cpp
new file mode 100644
index 00000000..bde792eb
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.cpp
@@ -0,0 +1,590 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "Strings.h"
+
+#include "ui_StudioAppPrefsPage.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "UICOptions.h"
+#include "Doc.h"
+#include "StudioAppPrefsPage.h"
+#include "StudioConst.h"
+#include "StudioProjectSettings.h"
+#include "StudioPreferences.h"
+#include "StudioApp.h"
+#include "StudioPreferences.h"
+#include "StringLoader.h"
+#include "CommonConstants.h"
+#include "Views.h"
+#include "UICDMStudioSystem.h"
+#include "ClientDataModelBridge.h"
+#include "Core.h"
+#include "IStudioRenderer.h"
+
+#include <QColorDialog>
+#include <QMessageBox>
+
+#define WM_PREVIEW_DYNAMIC_CONTROLS WM_USER + 1200
+const long MIN_PAGESIZE = 380;
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioAppPrefsPage property page
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CStudioAppPrefsPage::CStudioAppPrefsPage(QWidget *parent)
+ : CStudioPreferencesPropPage(parent)
+ , m_nudgeValue(0.0)
+ , m_TimebarShowTime(FALSE)
+ , m_InterpolationIsSmooth(FALSE)
+ , m_ui(new Ui::StudioAppPrefsPage)
+{
+ m_Font = QFont(CStudioPreferences::GetFontFaceName());
+ m_Font.setPixelSize(CStudioPreferences::fontSize());
+
+ // Create a bold font for the group box text
+ m_BoldFont = m_Font;
+ m_BoldFont.setBold(true);
+
+ OnInitDialog();
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CStudioAppPrefsPage::~CStudioAppPrefsPage()
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioAppPrefsPage message handlers
+
+void CStudioAppPrefsPage::OnInitDialog()
+{
+ m_ui->setupUi(this);
+ m_ui->m_editNudgeAmount->setValidator(new QDoubleValidator(this));
+
+ // Add tool tips for controls
+ m_ui->m_editNudgeAmount->setToolTip(::LoadResourceString(IDS_PREFS_NUDGEAMOUNT).toQString());
+ m_ui->m_DefaultInterpolation->setToolTip(::LoadResourceString(IDS_PREFS_INTERPOLATIONDEFAULT).toQString());
+ m_ui->m_checkTimelineAbsoluteSnapping->setToolTip(
+ ::LoadResourceString(IDS_PREFS_TIMELINEGRIDSNAPPING).toQString());
+ m_ui->m_SnapRangeCombo->setToolTip(::LoadResourceString(IDS_PREFS_TIMELINEGRIDRESOLUTION).toQString());
+ m_ui->m_buttonRestoreDefaults->setToolTip(::LoadResourceString(IDS_PREFS_RESTOREDEFAULTS).toQString());
+ m_ui->m_EditViewBGColor->setAutoFillBackground(true);
+
+ // Set fonts for child windows.
+ for (auto w : findChildren<QWidget *>())
+ w->setFont(m_Font);
+
+ // Make the group text bold
+ for (auto w : findChildren<QGroupBox *>())
+ w->setFont(m_BoldFont);
+
+#ifndef INCLUDE_EDIT_CAMERA
+ ASSERT(0);
+ // This won't work as all the controls have to move accordingly. Don't think INCLUDE_EDIT_CAMERA
+ // will be undefined
+ // Hide controls related to Edit Camera
+ m_ui->m_groupBoxEditingView->setVisible(false);
+#endif
+
+ // Load the settings for the controls
+ LoadSettings();
+
+ auto activated = static_cast<void(QComboBox::*)(int)>(&QComboBox::activated);
+ connect(m_ui->m_buttonRestoreDefaults, &QPushButton::clicked, this, &CStudioAppPrefsPage::OnButtonRestoreDefaults);
+ connect(m_ui->m_DefaultInterpolation, activated, this, &CStudioAppPrefsPage::OnSelChangeInterpolationDefault);
+ connect(m_ui->m_SnapRangeCombo, activated, this, &CStudioAppPrefsPage::OnSelChangeSnapRange);
+ connect(m_ui->m_checkTimelineAbsoluteSnapping, &QCheckBox::clicked, this, &CStudioAppPrefsPage::OnCheckTimelineAbsoluteSnapping);
+ connect(m_ui->m_EditViewBGColor, &QPushButton::clicked, this, &CStudioAppPrefsPage::OnBgColorButtonClicked);
+ connect(m_ui->m_editNudgeAmount, &QLineEdit::textEdited, this, &CStudioAppPrefsPage::OnChangeEditNudgeAmount);
+ connect(m_ui->m_EditViewStartupView, activated, this, &CStudioAppPrefsPage::OnSelChangeStartupView);
+ connect(m_ui->m_PreviewSelector, activated, this, &CStudioAppPrefsPage::OnChangePreviewConfiguration);
+}
+
+//==============================================================================
+/**
+ * LoadSettings: Load the settings from the CDoc and set the control values.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::LoadSettings()
+{
+ m_nudgeValue = CStudioPreferences::GetNudgeAmount();
+
+ // Get the Interpolation Preference
+ Q3DStudio::CString theComboItem;
+ theComboItem = ::LoadResourceString(IDS_PREF_INTERPOLATION_1);
+ m_ui->m_DefaultInterpolation->addItem(theComboItem.toQString());
+ theComboItem = ::LoadResourceString(IDS_PREF_INTERPOLATION_2);
+ m_ui->m_DefaultInterpolation->addItem(theComboItem.toQString());
+
+ long theInterpolationPref = 0;
+ if (CStudioPreferences::GetInterpolation())
+ theInterpolationPref = 0;
+ else
+ theInterpolationPref = 1;
+ m_ui->m_DefaultInterpolation->setCurrentIndex(theInterpolationPref);
+
+ // Timeline snapping grid
+ m_ui->m_checkTimelineAbsoluteSnapping->setChecked(
+ CStudioPreferences::IsTimelineSnappingGridActive());
+
+ // Load the combo boxes with values from the string table so that they are localizable.
+ // The scale mode
+ (void)theComboItem;
+ theComboItem = ::LoadResourceString(IDS_PREF_SNAPRANGE_1);
+ m_ui->m_SnapRangeCombo->addItem(theComboItem.toQString());
+ theComboItem = ::LoadResourceString(IDS_PREF_SNAPRANGE_2);
+ m_ui->m_SnapRangeCombo->addItem(theComboItem.toQString());
+ theComboItem = ::LoadResourceString(IDS_PREF_SNAPRANGE_3);
+ m_ui->m_SnapRangeCombo->addItem(theComboItem.toQString());
+ long theResolution = (long)CStudioPreferences::GetTimelineSnappingGridResolution();
+ m_ui->m_SnapRangeCombo->setCurrentIndex(theResolution);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ // Edit View Background color
+ // TODO: Visualize selected color on the bg color change button
+ InitEditStartViewCombo();
+#endif
+
+ EnableOptions();
+
+ LoadPreviewSelections();
+
+ m_ui->m_editNudgeAmount->setText(QString::number(m_nudgeValue));
+ m_bgColor = CStudioPreferences::GetEditViewBackgroundColor();
+ updateColorButton();
+}
+
+void CStudioAppPrefsPage::updateColorButton()
+{
+ QPalette pal = m_ui->m_EditViewBGColor->palette();
+ pal.setColor(QPalette::Button, m_bgColor);
+ m_ui->m_EditViewBGColor->setPalette(pal);
+}
+
+//==============================================================================
+/**
+ * SaveSettings: Save the settings from the controls to the CDoc
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::SaveSettings()
+{
+ // Nudge amount
+ CStudioPreferences::SetNudgeAmount(m_nudgeValue);
+
+ // Default interpolation
+ g_StudioApp.GetCore()->GetDoc()->SetDefaultKeyframeInterpolation(
+ m_ui->m_DefaultInterpolation->currentIndex() == 0);
+
+ // Timeline snapping grid
+ CStudioPreferences::SetTimelineSnappingGridActive(
+ m_ui->m_checkTimelineAbsoluteSnapping->isChecked());
+ long theCurrentSelection = m_ui->m_SnapRangeCombo->currentIndex();
+ CStudioPreferences::SetTimelineSnappingGridResolution((ESnapGridResolution)theCurrentSelection);
+
+#ifdef INCLUDE_EDIT_CAMERA
+ // Edit View Background Color
+ CStudioPreferences::SetEditViewBackgroundColor(m_bgColor);
+ //
+ // g_StudioApp.GetCore()->GetDoc( )->SetEditViewBackgroundColor( theColor );
+
+ // Preferred Startup View
+ long theSel = m_ui->m_EditViewStartupView->currentIndex();
+ long theNumItems = m_ui->m_EditViewStartupView->count();
+ CStudioPreferences::SetPreferredStartupView(
+ (theSel == theNumItems - 1) ? -1 : theSel); // -1 for deployment view
+// g_StudioApp.GetCore()->GetDoc( )->UpdateClientScene( false );
+#endif
+
+ SavePreviewSettings();
+}
+
+//==============================================================================
+/**
+ * OnApply: Handler for the Apply button
+ *
+ * @param None
+ */
+//==============================================================================
+bool CStudioAppPrefsPage::OnApply()
+{
+ // Apply was clicked - save settings and disabled the Apply button
+ this->SaveSettings();
+
+ this->SetModified(FALSE);
+
+ // Request that the renderer refreshes as settings may have changed
+ g_StudioApp.GetRenderer().RequestRender();
+
+ return CStudioPreferencesPropPage::OnApply();
+}
+
+//==============================================================================
+/**
+ * OnOK: Handler for the OK button
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnOK()
+{
+ CStudioPreferencesPropPage::OnOK();
+}
+
+//==============================================================================
+/**
+ * OnCancel: Handler for the Cancel button
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnCancel()
+{
+#ifdef INCLUDE_EDIT_CAMERA
+ // if the edit view background color was changed, reset it back to the original
+ // value
+ CColor theOrigColor = CStudioPreferences::GetEditViewBackgroundColor();
+ if (m_bgColor != theOrigColor) {
+ // g_StudioApp.GetCore()->GetDoc( )->SetEditViewBackgroundColor( theOrigColor );
+ // g_StudioApp.GetCore()->GetDoc( )->UpdateClientScene( false );
+ }
+#endif
+ CStudioPreferencesPropPage::OnCancel();
+}
+
+//==============================================================================
+/**
+ * OnButtonRestoreDefaults: Restore the defaults and exit the preferences.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnButtonRestoreDefaults()
+{
+ Q3DStudio::CString theMessage;
+ Q3DStudio::CString theTitle;
+ int theChoice = 0;
+
+ // Load the text strings for the message box
+ theTitle = ::LoadResourceString(IDS_PREF_RESTOREDEFAULT_TITLE);
+ theMessage = ::LoadResourceString(IDS_PREF_RESTOREDEFAULT_TEXT);
+
+ // Ask the user if she really wants to do this
+ theChoice = QMessageBox::question(this, theTitle.toQString(), theMessage.toQString());
+
+ // If the "yes" button was selected
+ if (theChoice == QMessageBox::Yes) {
+ // Restore default preferences by passing PREFS_RESET_DEFAULTS back
+ // to the CStudioDocPreferences (that called this preferences sheet)
+ CStudioPreferencesPropPage::EndDialog(PREFS_RESET_DEFAULTS);
+ }
+}
+
+//==============================================================================
+/**
+ * OnSelChangeInterpolationDefault: CBN_SELCHANGE handler for the
+ * IDC_INTERPOLATION_DEFAULT combo
+ *box.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnSelChangeInterpolationDefault()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeEditNudgeAmount: EN_UPDATE handler for the IDC_EDIT_NUDGE
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnChangeEditNudgeAmount()
+{
+ QString editStr = m_ui->m_editNudgeAmount->text();
+ m_nudgeValue = editStr.toDouble();
+ this->SetModified(true);
+}
+
+//==============================================================================
+/**
+ * OnSelChangeSnapRange: CBN_SELCHANGE handler for the IDC_SNAPRANGE combo box.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnSelChangeSnapRange()
+{
+ this->SetModified(true);
+}
+
+//==============================================================================
+/**
+ * OnCheckTimelineAbsoluteSnapping: Handler for the IDC_CHECK_TIMELINEABSOLUTESNAPPING
+ *checkbox.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnCheckTimelineAbsoluteSnapping()
+{
+ this->SetModified(true);
+ this->EnableOptions();
+}
+
+//==============================================================================
+/**
+ * EnableOptions: Enable/disable options.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioAppPrefsPage::EnableOptions()
+{
+ m_ui->m_SnapRangeCombo->setEnabled(m_ui->m_checkTimelineAbsoluteSnapping->isChecked());
+}
+
+//==============================================================================
+/**
+ * OnSelChangeStartupView: CBN_SELCHANGE handler for the IDC_COMBO_EDIT_STARTUP_VIEW
+ * Combo box
+ */
+void CStudioAppPrefsPage::OnSelChangeStartupView()
+{
+ this->SetModified(true);
+}
+
+//==============================================================================
+/**
+ * Initialise the combo box that displays the preferred startup view.
+ * Set the initial selection to that saved to the preferences
+ */
+//==============================================================================
+void CStudioAppPrefsPage::InitEditStartViewCombo()
+{
+ Q3DStudio::IStudioRenderer &theRenderer = g_StudioApp.GetRenderer();
+ QStringList theCameraNames;
+ theRenderer.GetEditCameraList(theCameraNames);
+ for (size_t idx = 0, end = theCameraNames.size(); idx < end; ++idx) {
+ m_ui->m_EditViewStartupView->addItem(
+ theCameraNames.at(idx));
+ m_ui->m_EditViewStartupView->setItemData(m_ui->m_EditViewStartupView->count() - 1, QVariant((int)idx + 1));
+ }
+
+ m_ui->m_EditViewStartupView->addItem("--------------------------");
+ m_ui->m_EditViewStartupView->setItemData(m_ui->m_EditViewStartupView->count() - 1, -1); // set to an invalid pointer
+ // add the deployment view as the last selection
+ m_ui->m_EditViewStartupView->addItem(::LoadResourceString(IDS_SCENE_CAMERA_VIEW).toQString());
+ m_ui->m_EditViewStartupView->setItemData(m_ui->m_EditViewStartupView->count() - 1, 0);
+
+ long thePreferredView = CStudioPreferences::GetPreferredStartupView();
+ long theNumItems = m_ui->m_EditViewStartupView->count();
+ if (thePreferredView == -1) // deployment view
+ m_ui->m_EditViewStartupView->setCurrentIndex(theNumItems - 1); // set to the last one
+ else if (thePreferredView < theNumItems - 1)
+ m_ui->m_EditViewStartupView->setCurrentIndex(thePreferredView);
+ else // possibly from old content where cameras are removed
+ m_ui->m_EditViewStartupView->setCurrentIndex(0);
+}
+
+void CStudioAppPrefsPage::LoadPreviewSelections()
+{
+ // Load the configurations from all the .build files
+ Q3DStudio::CBuildConfigurations &theConfig = g_StudioApp.GetCore()->GetBuildConfigurations();
+ Q3DStudio::CBuildConfigurations::TBuildConfigurations theConfigurations =
+ theConfig.GetConfigurations();
+ Q3DStudio::CBuildConfigurations::TBuildConfigurations::iterator theIter;
+ for (theIter = theConfigurations.begin(); theIter != theConfigurations.end(); ++theIter) {
+ const Q3DStudio::CString &theConfig = theIter->first;
+ m_ui->m_PreviewSelector->addItem(theConfig.toQString());
+ m_ui->m_PreviewSelector->setItemData(m_ui->m_PreviewSelector->count() - 1,
+ QVariant::fromValue(theIter->second));
+ }
+
+ int thePreviewSelected = m_ui->m_PreviewSelector->findText(CStudioPreferences::GetPreviewConfig().toQString());
+ m_ui->m_PreviewSelector->setCurrentIndex(thePreviewSelected);
+ if (thePreviewSelected == -1) {
+ // select the first build configuration, or if no conriguration, the first application, i.e.
+ // AMPlayer
+ m_ui->m_PreviewSelector->setCurrentIndex(0);
+ long thePreviewCount = m_ui->m_PreviewSelector->count();
+ for (long theIndex = 0; theIndex < thePreviewCount; ++theIndex) {
+ if (m_ui->m_PreviewSelector->itemData(theIndex).value<Q3DStudio::CBuildConfiguration *>() != nullptr) {
+ m_ui->m_PreviewSelector->setCurrentIndex(theIndex);
+ break;
+ }
+ }
+ }
+
+ LoadBuildProperties();
+}
+
+//==============================================================================
+/**
+ * When the build configuration is changed, all the properties have to be updated.
+ */
+//==============================================================================
+void CStudioAppPrefsPage::OnChangePreviewConfiguration()
+{
+ LoadBuildProperties();
+}
+
+void CStudioAppPrefsPage::OnBgColorButtonClicked()
+{
+ QColorDialog dlg(this);
+ dlg.setCurrentColor(m_bgColor);
+ if (dlg.exec() == QDialog::Accepted) {
+ m_bgColor = dlg.selectedColor();
+ updateColorButton();
+ }
+
+ this->SetModified(true);
+}
+
+//==============================================================================
+/**
+ * Load the build properties for the current preview application selected
+ */
+//==============================================================================
+void CStudioAppPrefsPage::LoadBuildProperties()
+{
+ // Remove those dynamic controls
+ RemovePreviewPropertyControls();
+
+ if (m_ui->m_PreviewSelector->count() > 0) {
+ Q3DStudio::CBuildConfiguration *theConfig =
+ m_ui->m_PreviewSelector->itemData(m_ui->m_PreviewSelector->currentIndex()).value<Q3DStudio::CBuildConfiguration *>();
+ if (theConfig) {
+ // Only configuration read from .build files will have the ItemDataPtr set.
+
+ Q3DStudio::CBuildConfiguration::TConfigProperties &theProperties =
+ theConfig->GetBuildProperties();
+
+ auto layout = qobject_cast<QFormLayout *>(m_ui->groupBoxPreview->layout());
+ auto activated = static_cast<void(QComboBox::*)(int)>(&QComboBox::activated);
+
+ if (theProperties.empty() == false) {
+ Q3DStudio::CBuildConfiguration::TConfigProperties::iterator theIter;
+
+ for (theIter = theProperties.begin(); theIter != theProperties.end(); ++theIter) {
+ Q3DStudio::CBuildConfiguration::TConfigPropertyValues &theValues =
+ theIter->GetAcceptableValues();
+ // Only create the combo if there is more than 1 choices
+ if (theValues.size() > 1) {
+ Q3DStudio::CBuildConfiguration::TConfigPropertyValues::iterator
+ theValueIter;
+ long theMaxLength = 0;
+ for (theValueIter = theValues.begin(); theValueIter != theValues.end();
+ ++theValueIter) {
+ long theLabelLength = theValueIter->GetLabel().Length();
+ if (theLabelLength > theMaxLength)
+ theMaxLength = theLabelLength;
+ }
+
+ QLabel *theStaticText = new QLabel(theIter->GetLabel().toQString());
+ theStaticText->setFont(m_Font);
+ QComboBox *thePropertyDropdown = new QComboBox();
+ connect(thePropertyDropdown, activated, [&]() {SetModified(true);});
+ thePropertyDropdown->setFont(m_Font);
+ layout->addRow(theStaticText, thePropertyDropdown);
+
+ m_BuildProperties.push_back(std::make_pair(
+ &*theIter, std::make_pair(theStaticText, thePropertyDropdown)));
+
+ Q3DStudio::CString thePropertyValue =
+ CStudioPreferences::GetPreviewProperty(theIter->GetName());
+ for (theValueIter = theValues.begin(); theValueIter != theValues.end();
+ ++theValueIter) {
+ thePropertyDropdown->addItem(theValueIter->GetLabel().toQString());
+ thePropertyDropdown->setItemData(thePropertyDropdown->count() - 1, QVariant::fromValue(&*theValueIter));
+ if (theValueIter->GetName() == thePropertyValue)
+ thePropertyDropdown->setCurrentIndex(thePropertyDropdown->count() - 1);
+ }
+
+ // Select the first entry
+ if (thePropertyDropdown->currentIndex() == -1)
+ thePropertyDropdown->setCurrentIndex(0);
+ }
+ }
+ }
+ }
+ }
+}
+
+void CStudioAppPrefsPage::SavePreviewSettings()
+{
+ QString thePreviewApp = m_ui->m_PreviewSelector->currentText();
+ CStudioPreferences::SetPreviewConfig(Q3DStudio::CString::fromQString(thePreviewApp));
+
+ std::list<TBuildNameControlPair>::iterator theIter;
+ for (theIter = m_BuildProperties.begin(); theIter != m_BuildProperties.end(); ++theIter) {
+ QComboBox *theCombo = theIter->second.second;
+ Q3DStudio::CString theName = theIter->first->GetName();
+ Q3DStudio::CBuildConfiguration::SConfigPropertyValue *thePropertyValue =
+ theCombo->itemData(theCombo->currentIndex()).value<Q3DStudio::CBuildConfiguration::SConfigPropertyValue *>();
+ CStudioPreferences::SetPreviewProperty(theName, thePropertyValue->GetName());
+ }
+}
+
+//==============================================================================
+/**
+ * Remove all the dynamically added controls that was read in from the build file
+ */
+//==============================================================================
+void CStudioAppPrefsPage::RemovePreviewPropertyControls()
+{
+ // Remove the created control
+ std::list<TBuildNameControlPair>::iterator theIter;
+ for (theIter = m_BuildProperties.begin(); theIter != m_BuildProperties.end(); ++theIter) {
+ delete theIter->second.first;
+ delete theIter->second.second;
+ }
+ m_BuildProperties.clear();
+}
diff --git a/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.h b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.h
new file mode 100644
index 00000000..a3be36c2
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#if !defined(AFX_STUDIOAPPPREFSPAGE_H__FA329789_EEDD_4439_B6F6_AAD0FED5285F__INCLUDED_)
+#define AFX_STUDIOAPPPREFSPAGE_H__FA329789_EEDD_4439_B6F6_AAD0FED5285F__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "BuildConfigParser.h"
+
+#include "StudioPreferencesPropSheet.h"
+
+class QComboBox;
+class QLabel;
+
+class CStudioApp;
+/////////////////////////////////////////////////////////////////////////////
+// CStudioAppPrefsPage dialog
+
+namespace Ui
+{
+ class StudioAppPrefsPage;
+}
+
+class CStudioAppPrefsPage : public CStudioPreferencesPropPage
+{
+ Q_OBJECT
+protected:
+ typedef std::pair<QLabel *, QComboBox *> TBuildLabelDropdownPair;
+ typedef std::pair<Q3DStudio::CBuildConfiguration::SConfigProperty *, TBuildLabelDropdownPair>
+ TBuildNameControlPair;
+
+ // Construction
+public:
+ explicit CStudioAppPrefsPage(QWidget *parent = nullptr);
+ ~CStudioAppPrefsPage();
+
+ // Dialog Data
+ QColor m_bgColor;
+
+ double m_nudgeValue;
+
+public:
+ bool OnApply() override;
+ void OnOK() override;
+ void OnCancel() override;
+
+ // Implementation
+protected:
+ BOOL m_TimebarShowTime; ///< TRUE if timebars are to display their time value
+ BOOL m_InterpolationIsSmooth; ///< TRUE if default interpolation is smooth
+ QFont m_Font; ///< Font for text
+ QFont m_BoldFont; ///< Bold font for drawing the group boxes
+ void EnableOptions();
+ void LoadSettings();
+ void SaveSettings();
+
+ // Generated message map functions
+ virtual void OnInitDialog();
+ void OnButtonRestoreDefaults();
+ void OnSelChangeInterpolationDefault();
+ void OnSelChangeSnapRange();
+ void OnCheckTimelineAbsoluteSnapping();
+ void OnChangeEditNudgeAmount();
+ void OnSelChangeStartupView();
+ void OnChangePreviewConfiguration();
+ void OnBgColorButtonClicked();
+
+protected: // helper functions
+ void InitEditStartViewCombo();
+
+protected:
+ std::list<TBuildNameControlPair>
+ m_BuildProperties; ///< List of build properties, either ComboBox or Static
+
+ void LoadPreviewSelections();
+ void LoadBuildProperties();
+ void SavePreviewSettings();
+ void RemovePreviewPropertyControls();
+
+ QScopedPointer<Ui::StudioAppPrefsPage> m_ui;
+
+private:
+ void updateColorButton();
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STUDIOAPPPREFSPAGE_H__FA329789_EEDD_4439_B6F6_AAD0FED5285F__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.ui b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.ui
new file mode 100644
index 00000000..5e1b88c5
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.ui
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StudioAppPrefsPage</class>
+ <widget class="QWidget" name="StudioAppPrefsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>347</width>
+ <height>387</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>General</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Nudge Increment</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_editNudgeAmount</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Default Interpolation</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_DefaultInterpolation</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="m_DefaultInterpolation"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="m_checkTimelineAbsoluteSnapping">
+ <property name="text">
+ <string>Timeline Snapping Grid</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="m_SnapRangeCombo"/>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="m_editNudgeAmount"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="m_groupBoxEditingView">
+ <property name="title">
+ <string>Editing View</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Background Color</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_EditViewBGColor</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" colspan="2">
+ <widget class="QPushButton" name="m_EditViewBGColor">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Preferred Startup View</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_EditViewStartupView</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" colspan="2">
+ <widget class="QComboBox" name="m_EditViewStartupView"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="m_buttonRestoreDefaults">
+ <property name="maximumSize">
+ <size>
+ <width>293</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Restore Defaults</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBoxPreview">
+ <property name="title">
+ <string>Preview</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Configuration</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_PreviewSelector</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="m_PreviewSelector"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/Authoring/Studio/_Win/UI/StudioPaletteBar.cpp b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.cpp
new file mode 100644
index 00000000..747ba442
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioPaletteBar.h"
+#include "Preferences.h"
+#include "StudioConst.h"
+#include "PaletteState.h"
+#include "StudioApp.h"
+
+//==============================================================================
+// Message Maps
+//==============================================================================
+BEGIN_MESSAGE_MAP(CStudioPaletteBar, CViewBar)
+//{{AFX_MSG_MAP(CStudioPaletteBar)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+// Constructors/Destructors
+//==============================================================================
+
+CStudioPaletteBar::CStudioPaletteBar()
+{
+}
+
+CStudioPaletteBar::~CStudioPaletteBar()
+{
+}
+
+void CStudioPaletteBar::SetHorz(CSize inSize)
+{
+ m_szHorz.cx = max(m_szMinHorz.cx, inSize.cx);
+ m_szHorz.cy = max(m_szMinHorz.cy, inSize.cy);
+}
+
+void CStudioPaletteBar::SetVert(CSize inSize)
+{
+ m_szVert.cx = max(m_szMinVert.cx, inSize.cx);
+ m_szVert.cy = max(m_szMinVert.cy, inSize.cy);
+}
+
+void CStudioPaletteBar::SetFloat(CSize inSize)
+{
+ m_szFloat.cx = max(m_szMinFloat.cx, inSize.cx);
+ m_szFloat.cy = max(m_szMinFloat.cy, inSize.cy);
+}
+
+//==============================================================================
+/**
+ * Create: A wrapper around the CViewBar::Create() method.
+ *
+ * Simplifies the create parameters for the palette bar.
+ *
+ * @return BOOL The result from the Create() call (FALSE if unsuccessful)
+ */
+BOOL CStudioPaletteBar::Create(CString inTitle, CCreateContext *inCreateContext, long inControlId,
+ CWnd *theParent /* = nullptr */)
+{
+ BOOL theReturnValue;
+
+ // Add the title of the bar to the registry location.
+ m_PaletteName = inTitle;
+
+ // Create the palette bar.
+ theReturnValue =
+ CViewBar::Create(theParent, inCreateContext, inTitle, WS_CHILD | CBRS_TOP, inControlId);
+ ASSERT(theReturnValue == TRUE);
+
+ SetBarStyle(GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
+ EnableDocking(CBRS_ALIGN_ANY);
+
+ return theReturnValue;
+}
+
+//==============================================================================
+/**
+ * Call this function when the palette's view needs to be updated for the first
+ * time on application launch.
+ */
+void CStudioPaletteBar::InitialUpdate()
+{
+ // Send the update message to the attached CView
+ SendMessageToDescendants(WM_STUDIO_INITIALIZE_PALETTES, reinterpret_cast<WPARAM>(&g_StudioApp));
+}
+
+//==============================================================================
+/**
+ * Shows or hides the palette and saves the visibility.
+ *
+ * This function should be called instead of ShowWindow(), so that the visibility
+ * will be saved in the registry.
+ */
+void CStudioPaletteBar::ShowPalette(bool inState /* = true */)
+{
+ ShowWindow(inState ? SW_SHOW : SW_HIDE);
+ m_pDockSite->ShowControlBar(this, inState, FALSE);
+}
+
+//==============================================================================
+/**
+ * Query the view associated with this palette
+ */
+CView *CStudioPaletteBar::GetView()
+{
+ // Looks like the first grandchild is the view
+ return (CView *)GetWindow(GW_CHILD)->GetWindow(GW_CHILD);
+}
+
+//==============================================================================
+// Message Maps
+//==============================================================================
+BEGIN_MESSAGE_MAP(CStudioDialog, CMiniFrameWnd)
+//{{AFX_MSG_MAP(CStudioDialog)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+//==============================================================================
+// Constructors/Destructors
+//==============================================================================
+
+CStudioDialog::CStudioDialog()
+{
+}
+
+CStudioDialog::~CStudioDialog()
+{
+}
+
+//==============================================================================
+/**
+ * Create: A wrapper around the CMiniFrameWnd::Create() method.
+ *
+ * Simplifies the create parameters for the palette bar.
+ *
+ * @return BOOL The result from the Create() call (FALSE if unsuccessful)
+ */
+/*
+BOOL CStudioDialog::Create( CString inTitle, CCreateContext* inCreateContext, long inControlId,
+CWnd* theParent )
+{
+ BOOL theReturnValue;
+
+ // Add the title of the bar to the registry location.
+ m_DialogName = inTitle;
+
+ // Create the palette bar.
+ theReturnValue = CMiniFrameWnd::Create( theParent, inCreateContext, _T( inTitle ), WS_CHILD
+| CBRS_TOP, inControlId );
+ ASSERT( theReturnValue == TRUE );
+
+ SetBarStyle( GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC );
+ EnableDocking(CBRS_ALIGN_ANY);
+
+ return theReturnValue;
+}*/
+
+//==============================================================================
+/**
+* Create: A wrapper around the CMiniFrameWnd::Create() method.
+*
+* Simplifies the create parameters for the palette bar.
+*
+* @return BOOL The result from the Create() call (FALSE if unsuccessful)
+*/
+//==============================================================================
+BOOL CStudioDialog::Create(CString inTitle, CCreateContext *inCreateContext,
+ CWnd *theParent /* = nullptr */)
+{
+ CString theWndClass = AfxRegisterWndClass(CS_DBLCLKS, ::LoadCursor(nullptr, IDC_ARROW));
+ BOOL theReturnValue;
+
+ // Add the title of the bar to the registry location.
+ m_DialogName = inTitle;
+
+ // Create the palette bar.
+ theReturnValue = CFrameWnd::Create(
+ theWndClass, inTitle, WS_SYSMENU | MFS_SYNCACTIVE | WS_POPUP | WS_CAPTION | MFS_THICKFRAME,
+ CRect(300, 300, 550, 800), theParent, nullptr, 0, inCreateContext);
+
+ // Get the view to initialize.
+ this->InitialUpdateFrame(inCreateContext->m_pCurrentDoc, FALSE);
+
+ // Get a handle to the system menu on the palette window
+ CMenu *theSystemMenu = GetSystemMenu(FALSE);
+
+ // Remove the unwanted system menu items
+ theSystemMenu->DeleteMenu(SC_MINIMIZE, MF_BYCOMMAND);
+ theSystemMenu->DeleteMenu(SC_MAXIMIZE, MF_BYCOMMAND);
+ theSystemMenu->DeleteMenu(SC_RESTORE, MF_BYCOMMAND);
+
+ return theReturnValue;
+}
+
+//==============================================================================
+/**
+ * Call this function when the palette's view needs to be updated for the first
+ * time on application launch.
+ */
+void CStudioDialog::InitialUpdate()
+{
+ // Send the update message to the attached CView
+ SendMessageToDescendants(WM_STUDIO_INITIALIZE_PALETTES, reinterpret_cast<WPARAM>(&g_StudioApp));
+}
+
+//==============================================================================
+/**
+ * Shows or hides the dialog and saves the visibility.
+ *
+ * This function should be called instead of ShowWindow(), so that the visibility
+ * will be saved in the registry.
+ */
+void CStudioDialog::ShowDialog(bool inState /* = true */)
+{
+ ShowWindow(inState ? SW_SHOW : SW_HIDE);
+ // m_pDockSite->ShowControlBar( this, inState, FALSE );
+}
+
+//==============================================================================
+/**
+ * Query the view associated with this palette
+ */
+CView *CStudioDialog::GetView()
+{
+ // Looks like the first grandchild is the view
+ return (CView *)GetWindow(GW_CHILD)->GetWindow(GW_CHILD);
+}
diff --git a/src/Authoring/Studio/_Win/UI/StudioPaletteBar.h b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.h
new file mode 100644
index 00000000..eed3fd05
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_STUDIO_PALETTE_BAR_H
+#define INCLUDED_STUDIO_PALETTE_BAR_H 1
+
+#pragma once
+
+#include "ViewBar.h"
+
+class CStudioApp;
+class CPaletteState;
+class CStudioApp;
+
+class CStudioPaletteBar : public CViewBar
+{
+public:
+ CStudioPaletteBar();
+ virtual ~CStudioPaletteBar();
+
+ virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, long inControlId,
+ CWnd *theParent = nullptr);
+
+ void ShowPalette(bool inState = true);
+ void InitialUpdate();
+ CView *GetView();
+ CSize GetHorz() { return m_szHorz; }
+ void SetHorz(CSize inSize);
+ CSize GetVert() { return m_szVert; }
+ void SetVert(CSize inSize);
+ CSize GetFloat() { return m_szFloat; }
+ void SetFloat(CSize inSize);
+
+protected:
+ Q3DStudio::CString m_PaletteName;
+
+ //{{AFX_MSG(CStudioPaletteBar)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+class CStudioDialog : public CMiniFrameWnd
+{
+public:
+ CStudioDialog();
+ virtual ~CStudioDialog();
+
+ virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, CWnd *theParent = nullptr);
+
+ void ShowDialog(bool inState = true);
+ void InitialUpdate();
+ CView *GetView();
+
+protected:
+ Q3DStudio::CString m_DialogName;
+
+ //{{AFX_MSG(CStudioDialog)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif // INCLUDED_STUDIO_PALETTE_BAR_H
diff --git a/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.cpp b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.cpp
new file mode 100644
index 00000000..eb645d5e
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+
+#include "ui_StudioPreferencesPropSheet.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioPreferences.h"
+#include "StudioPreferencesPropSheet.h"
+#include "StudioProjectSettingsPage.h"
+#include "StringLoader.h"
+
+#include <QPushButton>
+
+CStudioPreferencesPropPage::CStudioPreferencesPropPage(QWidget *parent)
+ : QWidget(parent)
+{
+}
+
+void CStudioPreferencesPropPage::SetModified(bool modified)
+{
+ setProperty("modified", modified);
+
+ auto s = sheet();
+ if (s) {
+ auto buttons = s->findChild<QDialogButtonBox *>();
+ bool anyModified = false;
+ for (auto page : s->findChildren<CStudioPreferencesPropPage *>())
+ anyModified |= page->property("modified").toBool();
+ buttons->button(QDialogButtonBox::Apply)->setEnabled(anyModified);
+ }
+}
+
+CStudioPreferencesPropSheet* CStudioPreferencesPropPage::sheet()
+{
+ QWidget *parent = parentWidget();
+ while (parent != nullptr) {
+ if (auto sheet = qobject_cast<CStudioPreferencesPropSheet *>(parent))
+ return sheet;
+ parent = parent->parentWidget();
+ }
+ return nullptr;
+}
+
+
+void CStudioPreferencesPropPage::EndDialog(int returnCode)
+{
+ auto s = sheet();
+ if (s)
+ s->done(returnCode);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioPreferencesPropSheet
+
+CStudioPreferencesPropSheet::CStudioPreferencesPropSheet(int nIDCaption, QWidget *pParentWnd,
+ int iSelectPage)
+ : QDialog(pParentWnd)
+ , m_ui(new Ui::StudioPreferencesPropSheet)
+{
+ setWindowTitle(::LoadResourceString(nIDCaption).toQString());
+ OnInitDialog();
+ m_ui->m_TabCtrl->setCurrentIndex(iSelectPage);
+}
+
+CStudioPreferencesPropSheet::CStudioPreferencesPropSheet(const QString &pszCaption, QWidget *pParentWnd,
+ int iSelectPage)
+ : QDialog(pParentWnd)
+ , m_ui(new Ui::StudioPreferencesPropSheet)
+{
+ setWindowTitle(pszCaption);
+ OnInitDialog();
+ m_ui->m_TabCtrl->setCurrentIndex(iSelectPage);
+}
+
+CStudioPreferencesPropSheet::~CStudioPreferencesPropSheet()
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioPreferencesPropSheet message handlers
+
+//==============================================================================
+/**
+ * OnInitDialog: Handle the WM_INITDIALOG message to initialize the property sheet.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioPreferencesPropSheet::OnInitDialog()
+{
+ m_ui->setupUi(this);
+ m_ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
+
+ m_Font = QFont(CStudioPreferences::GetFontFaceName(), 8);
+ setFont(m_Font);
+
+ connect(m_ui->buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked,
+ this, &CStudioPreferencesPropSheet::apply);
+}
+
+bool CStudioPreferencesPropSheet::apply()
+{
+ for (auto page : findChildren<CStudioPreferencesPropPage *>()) {
+ if (!page->OnApply())
+ return false;
+ }
+ return true;
+}
+
+void CStudioPreferencesPropSheet::accept()
+{
+ if (apply())
+ QDialog::accept();
+}
+
+void CStudioPreferencesPropSheet::reject()
+{
+ for (auto page : findChildren<CStudioPreferencesPropPage *>())
+ page->OnCancel();
+ QDialog::reject();
+}
diff --git a/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.h b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.h
new file mode 100644
index 00000000..7057ba0f
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#if !defined(AFX_STUDIOPREFERENCESPROPSHEET_H__FADC69CE_5F0E_4F7E_A906_ED6052BBECF6__INCLUDED_)
+#define AFX_STUDIOPREFERENCESPROPSHEET_H__FADC69CE_5F0E_4F7E_A906_ED6052BBECF6__INCLUDED_
+
+#pragma once
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include <QDialog>
+
+class CStudioProjectSettingsPage;
+class CStudioPreferencesPropSheet;
+class CStudioApp;
+
+namespace Ui
+{
+ class StudioPreferencesPropSheet;
+}
+
+class CStudioPreferencesPropPage : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit CStudioPreferencesPropPage(QWidget *parent = nullptr);
+
+ virtual bool OnApply() { OnOK(); SetModified(false); return true; }
+ virtual void OnOK() {}
+ virtual void OnCancel() {}
+
+protected:
+ CStudioPreferencesPropSheet* sheet();
+
+ void SetModified(bool modified);
+ void EndDialog(int returnCode);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioPreferencesPropSheet
+
+class CStudioPreferencesPropSheet : public QDialog
+{
+ Q_OBJECT
+ // Construction
+public:
+ explicit CStudioPreferencesPropSheet(int nIDCaption, QWidget *pParentWnd = nullptr,
+ int iSelectPage = 0);
+ explicit CStudioPreferencesPropSheet(const QString &pszCaption, QWidget *pParentWnd = nullptr,
+ int iSelectPage = 0);
+
+protected:
+ QFont m_Font; // Font for text
+
+ // Implementation
+public:
+ virtual ~CStudioPreferencesPropSheet();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CStudioPreferencesPropSheet)
+ virtual void OnInitDialog();
+
+ bool apply();
+ void accept() override;
+ void reject() override;
+
+private:
+ QScopedPointer<Ui::StudioPreferencesPropSheet> m_ui;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STUDIOPREFERENCESPROPSHEET_H__FADC69CE_5F0E_4F7E_A906_ED6052BBECF6__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.ui b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.ui
new file mode 100644
index 00000000..813d6016
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.ui
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StudioPreferencesPropSheet</class>
+ <widget class="QDialog" name="StudioPreferencesPropSheet">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>484</width>
+ <height>466</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Studio Preferences</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTabWidget" name="m_TabCtrl">
+ <widget class="CStudioAppPrefsPage" name="m_AppPrefsPage">
+ <attribute name="icon">
+ <iconset resource="../../MainFrm.qrc">
+ <normaloff>:/res/prefstab-00.png</normaloff>:/res/prefstab-00.png</iconset>
+ </attribute>
+ <attribute name="title">
+ <string>Studio</string>
+ </attribute>
+ </widget>
+ <widget class="CStudioProjectSettingsPage" name="m_ProjectSettingsPage">
+ <attribute name="icon">
+ <iconset resource="../../MainFrm.qrc">
+ <normaloff>:/res/prefstab-01.png</normaloff>:/res/prefstab-01.png</iconset>
+ </attribute>
+ <attribute name="title">
+ <string>Presentation Settings</string>
+ </attribute>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>CStudioProjectSettingsPage</class>
+ <extends>QWidget</extends>
+ <header>StudioProjectSettingsPage.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>CStudioAppPrefsPage</class>
+ <extends>QWidget</extends>
+ <header>StudioAppPrefsPage.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="../../MainFrm.qrc"/>
+ </resources>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>StudioPreferencesPropSheet</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>StudioPreferencesPropSheet</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.cpp b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.cpp
new file mode 100644
index 00000000..c2a7e26c
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.cpp
@@ -0,0 +1,385 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#include "stdafx.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+#include "ui_StudioProjectSettingsPage.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "StudioProjectSettingsPage.h"
+#include "StudioProjectSettings.h"
+#include "StudioApp.h"
+#include "Doc.h"
+#include "Views.h"
+#include "MainFrm.h"
+#include "CommonConstants.h"
+
+#include "StudioPreferences.h"
+#include "Core.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioProjectSettingsPage property page
+
+//==============================================================================
+/**
+ * Constructor: Initializes the object.
+ */
+//==============================================================================
+CStudioProjectSettingsPage::CStudioProjectSettingsPage(QWidget *parent)
+ : CStudioPreferencesPropPage(parent)
+ , m_AspectRatio(0.0f)
+ , m_ui(new Ui::StudioProjectSettingsPage)
+{
+ m_Font = QFont(CStudioPreferences::GetFontFaceName());
+ m_Font.setPixelSize(CStudioPreferences::fontSize());
+
+ // Create a bold font for the group box text
+ m_BoldFont = m_Font;
+ m_BoldFont.setBold(true);
+
+ OnInitDialog();
+}
+
+//==============================================================================
+/**
+ * Destructor: Releases the object.
+ */
+//==============================================================================
+CStudioProjectSettingsPage::~CStudioProjectSettingsPage()
+{
+}
+
+//==============================================================================
+// Message Map is defined by subclasses, since there is any specific handlers must be
+// defined within the BEGIN_MESSAGE_MAP macros.
+//==============================================================================
+
+/////////////////////////////////////////////////////////////////////////////
+// CStudioProjectSettingsPage message handlers
+
+//==============================================================================
+/**
+ * OnInitDialog: Handle the WM_INITDIALOG message.
+ *
+ * Initialize the dialog by setting the various control values.
+ *
+ * @param None
+ *
+ * @return Returns TRUE always.
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnInitDialog()
+{
+ m_ui->setupUi(this);
+
+ m_ui->m_ClientSizeWidth->setToolTip(::LoadResourceString(IDS_PREFS_PRESENTATIONWIDTH).toQString());
+ m_ui->m_ClientSizeHeight->setToolTip(::LoadResourceString(IDS_PREFS_PRESENTATIONHEIGHT).toQString());
+ m_ui->m_checkConstrainProportions->setToolTip(::LoadResourceString(IDS_PREFS_PRESENTATIONASPECTRATIO).toQString());
+ m_ui->m_Author->setToolTip(::LoadResourceString(IDS_PREFS_AUTHORNAME).toQString());
+ m_ui->m_Company->setToolTip(::LoadResourceString(IDS_PREFS_COMPANYNAME).toQString());
+
+ // Set fonts for child windows.
+ for (auto w : findChildren<QWidget *>())
+ w->setFont(m_Font);
+
+ // Make the group text bold
+ for (auto w : findChildren<QGroupBox *>())
+ w->setFont(m_BoldFont);
+
+ // Set the ranges of the client width and height
+ m_ui->m_ClientSizeWidth->setRange(1, 16384);
+ m_ui->m_ClientSizeHeight->setRange(1, 16384);
+
+ // Load the settings for the controls
+ this->LoadSettings();
+
+ auto valueChanged = static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged);
+ connect(m_ui->m_ClientSizeWidth, valueChanged, this, &CStudioProjectSettingsPage::OnChangeEditPresWidth);
+ connect(m_ui->m_ClientSizeHeight, valueChanged, this, &CStudioProjectSettingsPage::OnChangeEditPresHeight);
+ connect(m_ui->m_checkConstrainProportions, &QCheckBox::clicked, this, &CStudioProjectSettingsPage::OnCheckMaintainRatio);
+ connect(m_ui->m_Author, &QLineEdit::textEdited, this, &CStudioProjectSettingsPage::OnChangeAuthor);
+ connect(m_ui->m_Company, &QLineEdit::textEdited, this, &CStudioProjectSettingsPage::OnChangeCompany);
+}
+
+//==============================================================================
+/**
+ * LoadSettings: Load the settings from the project settings and set the control values.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::LoadSettings()
+{
+ // Get the Client size
+ CStudioProjectSettings *theProjectSettings = g_StudioApp.GetCore()->GetStudioProjectSettings();
+ CPt theClientSize = theProjectSettings->GetPresentationSize();
+
+ // Set client width & height
+ m_ui->m_ClientSizeWidth->setValue(theClientSize.x);
+ m_ui->m_ClientSizeHeight->setValue(theClientSize.y);
+
+ // Save the aspect ratio
+ m_AspectRatio = (double)theClientSize.x / (double)theClientSize.y;
+
+ // Maintain Aspect Ratio checkbox
+ m_ui->m_checkConstrainProportions->setChecked(theProjectSettings->GetMaintainAspect());
+
+ m_ui->m_checkPortraitFormat->setChecked(theProjectSettings->GetRotatePresentation());
+
+ // Author
+ m_ui->m_Author->setText(theProjectSettings->GetAuthor());
+
+ // Company
+ m_ui->m_Company->setText(theProjectSettings->GetCompany());
+}
+
+//==============================================================================
+/**
+ * SaveSettings: Save the settings from the controls to the project settings.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::SaveSettings()
+{
+ CPt theClientSize;
+ CStudioProjectSettings *theProjectSettings = g_StudioApp.GetCore()->GetStudioProjectSettings();
+
+ // Presentation width & height
+ theClientSize.x = m_ui->m_ClientSizeWidth->value();
+ theClientSize.y = m_ui->m_ClientSizeHeight->value();
+ theProjectSettings->SetPresentationSize(theClientSize);
+
+ // Author
+ QString theAuthor = m_ui->m_Author->text();
+ theProjectSettings->SetAuthor(theAuthor);
+
+ // Company
+ QString theCompany = m_ui->m_Company->text();
+ theProjectSettings->SetCompany(theCompany);
+
+ g_StudioApp.GetViews()->RecheckMainframeSizingMode();
+
+ // Maintain Aspect Ratio checkbox
+ theProjectSettings->SetMaintainAspect(m_ui->m_checkConstrainProportions->isChecked());
+
+ theProjectSettings->SetRotatePresentation(m_ui->m_checkPortraitFormat->isChecked());
+}
+
+//==============================================================================
+/**
+ * Generic function when settings are modified.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnSettingsModified()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnApply: Handler for the Apply button
+ *
+ * @param None
+ */
+//==============================================================================
+bool CStudioProjectSettingsPage::OnApply()
+{
+ // Apply was clicked - save settings and disabled the Apply button
+ this->SaveSettings();
+
+ this->SetModified(FALSE);
+
+ return CStudioPreferencesPropPage::OnApply();
+}
+
+//==============================================================================
+/**
+ * OnOK: Handler for the OK button
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnOK()
+{
+ CStudioPreferencesPropPage::OnOK();
+}
+
+//==============================================================================
+/**
+ * OnChangeEditPresWidth: EN_CHANGE handler for the IDC_EDIT_PRESWIDTH field
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeEditPresWidth()
+{
+ this->SetModified(TRUE);
+
+ // Should the aspect ratio be maintained?
+ if (m_ui->m_checkConstrainProportions->isChecked()) {
+ long thePresWidth, thePresHeight;
+
+ thePresWidth = m_ui->m_ClientSizeWidth->value();
+
+ // Change the height
+ thePresHeight = ((double)thePresWidth / m_AspectRatio);
+
+ QSignalBlocker sb(m_ui->m_ClientSizeHeight);
+ m_ui->m_ClientSizeHeight->setValue(thePresHeight);
+ }
+}
+
+//==============================================================================
+/**
+ * OnChangeEditPresHeight: EN_CHANGE handler for the IDC_EDIT_PRESHEIGHT field
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeEditPresHeight()
+{
+ this->SetModified(TRUE);
+
+ // Should the aspect ratio be maintained?
+ if (m_ui->m_checkConstrainProportions->isChecked()) {
+ long thePresWidth, thePresHeight;
+
+ thePresHeight = m_ui->m_ClientSizeHeight->value();
+
+ // Change the width
+ thePresWidth = ((double)thePresHeight * m_AspectRatio);
+
+ QSignalBlocker sb(m_ui->m_ClientSizeWidth);
+ m_ui->m_ClientSizeWidth->setValue(thePresWidth);
+ }
+}
+
+//==============================================================================
+/**
+ * OnCheckMaintainRatio: The aspect ratio checkbox has changed.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnCheckMaintainRatio()
+{
+ this->SetModified(TRUE);
+
+ long thePresWidth, thePresHeight;
+
+ // Get the width and height
+ thePresWidth = m_ui->m_ClientSizeWidth->value();
+ thePresHeight = m_ui->m_ClientSizeHeight->value();
+
+ // Save the Aspect Ratio
+ m_AspectRatio = (double)thePresWidth / (double)thePresHeight;
+}
+
+//==============================================================================
+/**
+ * OnChangeAuthor: EN_CHANGE handler for the IDC_AUTHOR field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeAuthor()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeCompany: EN_CHANGE handler for the IDC_COMPANY field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeCompany()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeSet1: EN_CHANGE handler for the IDC_SET1 field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeSet1()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeSet2: EN_CHANGE handler for the IDC_SET2 field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeSet2()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeSet3: EN_CHANGE handler for the IDC_SET3 field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeSet3()
+{
+ this->SetModified(TRUE);
+}
+
+//==============================================================================
+/**
+ * OnChangeSet5: EN_CHANGE handler for the IDC_SET5 field.
+ *
+ * @param None
+ */
+//==============================================================================
+void CStudioProjectSettingsPage::OnChangeSet5()
+{
+ this->SetModified(TRUE);
+}
diff --git a/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.h b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.h
new file mode 100644
index 00000000..64465e98
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#if !defined(AFX_STUDIOPROJECTSETTINGSPAGE_H__E3317E44_810D_4478_A7DD_CF8570B7C17C__INCLUDED_)
+#define AFX_STUDIOPROJECTSETTINGSPAGE_H__E3317E44_810D_4478_A7DD_CF8570B7C17C__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+//#include "ParameterColor.h"
+
+#include "StudioPreferencesPropSheet.h"
+
+#ifdef _USENEWCOLORPICKER_
+#include "StudioColorPicker.h"
+#endif
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CStudioApp;
+
+namespace Ui {
+ class StudioProjectSettingsPage;
+}
+
+//==============================================================================
+// Base class for the settings for different modes
+//==============================================================================
+class CStudioProjectSettingsPage : public CStudioPreferencesPropPage
+{
+ Q_OBJECT
+ // Construction
+public:
+ explicit CStudioProjectSettingsPage(QWidget *parent = nullptr);
+ ~CStudioProjectSettingsPage();
+
+ // Overrides
+ // ClassWizard generate virtual function overrides
+public:
+ bool OnApply() override;
+ void OnOK() override;
+
+ // Implementation
+protected:
+ double m_AspectRatio; ///< Stores the presentation width divided by the presentation height
+ QFont m_Font; ///< Font for text
+ QFont m_BoldFont; ///< Bold font for drawing the group boxes
+
+ void LoadSettings();
+ void SaveSettings();
+
+protected:
+ // Generated message map functions
+ virtual void OnInitDialog();
+ void OnChangeEditPresWidth();
+ void OnChangeEditPresHeight();
+ void OnCheckMaintainRatio();
+ void OnChangeAuthor();
+ void OnChangeCompany();
+ void OnSettingsModified();
+ void OnSelChangePreviewApp();
+ void OnCustomPreviewMore();
+ void OnChangeSet1();
+ void OnChangeSet2();
+ void OnChangeSet3();
+ void OnChangeSet5();
+
+ QScopedPointer<Ui::StudioProjectSettingsPage> m_ui;
+};
+
+#endif // !defined(AFX_STUDIOPROJECTSETTINGSPAGE_H__E3317E44_810D_4478_A7DD_CF8570B7C17C__INCLUDED_)
diff --git a/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.ui b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.ui
new file mode 100644
index 00000000..07a4bf65
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.ui
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>StudioProjectSettingsPage</class>
+ <widget class="QWidget" name="StudioProjectSettingsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>259</width>
+ <height>269</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Presentation</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Width x Height</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_ClientSizeWidth</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QSpinBox" name="m_ClientSizeWidth">
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="m_ClientSizeHeight">
+ <property name="buttonSymbols">
+ <enum>QAbstractSpinBox::NoButtons</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QCheckBox" name="m_checkConstrainProportions">
+ <property name="text">
+ <string>Constrain Proportions</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" colspan="2">
+ <widget class="QCheckBox" name="m_checkPortraitFormat">
+ <property name="text">
+ <string>Portrait Format</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Project Info</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Author</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_Author</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="m_Author"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Company</string>
+ </property>
+ <property name="buddy">
+ <cstring>m_Company</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="m_Company"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>m_ClientSizeWidth</tabstop>
+ <tabstop>m_ClientSizeHeight</tabstop>
+ <tabstop>m_checkConstrainProportions</tabstop>
+ <tabstop>m_checkPortraitFormat</tabstop>
+ <tabstop>m_Author</tabstop>
+ <tabstop>m_Company</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/Authoring/Studio/_Win/UI/TimeEditDlg.cpp b/src/Authoring/Studio/_Win/UI/TimeEditDlg.cpp
new file mode 100644
index 00000000..619d7651
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/TimeEditDlg.cpp
@@ -0,0 +1,524 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//=============================================================================
+// Prefix
+//=============================================================================
+
+#include "ui_timeeditdlg.h"
+
+#include "stdafx.h"
+#include "StudioPreferences.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+#include "TimeEditDlg.h"
+#include "IDoc.h"
+#include "Bindings/ITimelineKeyframesManager.h"
+
+#include <QFont>
+#include <QPalette>
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CTimeEditDlg::CTimeEditDlg(QWidget *pParent)
+ : QDialog(pParent)
+ , m_MaxTime(0)
+ , m_MaxTimeDisplay(0)
+ , m_MinTimeDisplay(0)
+ , m_InitialTime1(0)
+ , m_InitialTime2(0)
+ , m_MinOffset(0)
+ , m_SecOffset(0)
+ , m_MSecOffset(0)
+ , m_MinMinorOffset(0)
+ , m_SecMinorOffset(0)
+ , m_MSecMinorOffset(0)
+ , m_CursorPosition(0)
+ , m_TimeFormat(0)
+ , m_PreviousFormat(0)
+ , m_TimeInMins(0.0f)
+ , m_NumberOfDigitsDrop(0)
+ , m_ColonPosition1(0)
+ , m_ColonPosition2(0)
+ , m_ObjectAssociation(0)
+ , m_OffsetFromInitialTime(0)
+ , m_Time1(0)
+ , m_Time2(0)
+ , m_Doc(nullptr)
+ , m_KeyframesManager(nullptr)
+ , m_Callback(nullptr)
+ , m_ui(new Ui::TimeEditDlg)
+{
+ m_ui->setupUi(this);
+ setAutoFillBackground(true);
+
+ connect(m_ui->startTimeEdit, &QDateTimeEdit::timeChanged, this, &CTimeEditDlg::OnEnChangeTimeEdit1);
+ connect(m_ui->endTimeEdit, &QDateTimeEdit::timeChanged, this, &CTimeEditDlg::OnEnChangeTimeEdit2);
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CTimeEditDlg::~CTimeEditDlg()
+{
+ delete m_ui;
+}
+
+void CTimeEditDlg::SetKeyframesManager(ITimelineKeyframesManager *inKeyframesManager)
+{
+ m_KeyframesManager = inKeyframesManager;
+}
+
+//=============================================================================
+/**
+ * InitData: Initializes the Time Edit Dialog Box.
+ * @param inTime1 is the intial start time, which will be shown when the time edit
+ * dialog box pops up
+ * @param inTime2 is the intial end time, which will be shown when the time edit
+ * dialog box pops up
+ * @param inDoc this can be nullptr where its not applicable
+ * @param inObjectAssociation is the identifier for that identifies the object
+ * associated with the time edit dialog
+ *(e.g.
+ * playhead, keyframe, timebar)
+ */
+void CTimeEditDlg::ShowDialog(long inTime1, long inTime2, IDoc *inDoc, long inObjectAssociation,
+ ITimeChangeCallback *inCallback /*= nullptr*/)
+{
+ m_InitialTime1 = inTime1;
+ m_InitialTime2 = inTime2;
+ m_ObjectAssociation = inObjectAssociation;
+ m_Doc = inDoc;
+ m_Callback = inCallback;
+
+ m_OffsetFromInitialTime = 0;
+ m_NumberOfDigitsDrop = 0;
+ m_MinTimeDisplay = 0;
+ // if it is a Timebar, this will be adjusted, else this should be initialized to some value at
+ // least,
+ // for OverflowHandling to work correctly
+ m_MaxTimeDisplay = LONG_MAX;
+
+ // 9999:59:999 converted to milliseconds
+ m_MaxTime =
+ TimeConversion(9999, CONVERT_MIN_TO_MSEC) + TimeConversion(59, CONVERT_SEC_TO_MSEC) + 999;
+
+ m_TimeDisplay2 = FormatTime(m_InitialTime2);
+ // In cases Keyframes, where its only one set of time, do m_InitialTime1 later so that
+ // m_Min, etc. values are initializd to the valid values.
+ m_TimeDisplay1 = FormatTime(m_InitialTime1);
+
+ // Present the dialog
+ exec();
+}
+
+//==============================================================================
+/**
+ * FormatTime: Called to break up a given time in milliseconds into min:sec:msec
+ * store it in a string. The string is formatted in 99:59:999 form.
+ * @param inTime stores the time in milliseconds, which will be converted
+ * and stored in ioTimeString in 99:59:999 format.
+ * @return ioTimeString stores the result of the FormatTime method.
+ */
+QString CTimeEditDlg::FormatTime(long inTime)
+{
+ long theTime = inTime;
+ long hour = 0;
+ long min = 0;
+ long sec = 0;
+ long msec = 0;
+ // Translates the m_InitialTime1 (in milliseconds) into Minutes, Seconds and Milliseconds
+ if (inTime != 0) {
+ min = TimeConversion(theTime, CONVERT_MSEC_TO_MIN);
+ hour = min / 60;
+ theTime = theTime - TimeConversion(min, CONVERT_MIN_TO_MSEC);
+ min -= hour * 60;
+ sec = TimeConversion(theTime, CONVERT_MSEC_TO_SEC);
+ theTime = theTime - TimeConversion(sec, CONVERT_SEC_TO_MSEC);
+ msec = theTime;
+ }
+ return QString::asprintf("%02d:%02d:%02d:%03d", hour, min, sec, msec);
+}
+
+//==============================================================================
+/**
+ * OnInitDialog: Handle the WM_INITDIALOG message.
+ * @param None
+ * @return Returns TRUE always.
+ */
+void CTimeEditDlg::showEvent(QShowEvent *ev)
+{
+ OnInitDialog();
+ QDialog::showEvent(ev);
+}
+
+
+void CTimeEditDlg::OnInitDialog()
+{
+ // Hide the window items associated with end time.
+ if (m_ObjectAssociation != TIMEBAR)
+ HideUnnecessaryFields();
+ m_ui->startTimeEdit->setTime(QTime::fromString(m_TimeDisplay1, "hh:mm:ss:zzz"));
+ Q3DStudio::CString theTitle;
+ // Display the window captions for the correct object type
+ switch (m_ObjectAssociation) {
+ case PLAYHEAD:
+ theTitle = ::LoadResourceString(IDS_TIME_EDIT_DLG_GO_TO_TIME);
+ setWindowTitle(theTitle.toQString());
+ break;
+ case ASSETKEYFRAME:
+ theTitle = ::LoadResourceString(IDS_TIME_EDIT_DLG_SET_KEYFRAME_TIME);
+ setWindowTitle(theTitle.toQString());
+ break;
+ case TIMEBAR:
+ theTitle = ::LoadResourceString(IDS_TIME_EDIT_DLG_SET_TIMEBAR_TIME);
+ // m_TimeEditBoxNumber is a flag that switches the output between
+ // the first and second text box.
+ // When m_TimeEditBoxNumber = EDITBOX1, we are writing to the first text box
+ // (the one that appears on top).
+ // When it is EDITBOX2, the SetTimeEdit will write to the second text box.
+ setWindowTitle(theTitle.toQString());
+ m_ui->endTimeEdit->setTime(QTime::fromString(m_TimeDisplay2, "hh:mm:ss:zzz"));
+ break;
+ }
+}
+//==============================================================================
+/**
+ * accept: Upon clicking ok, the dialog will be exited
+ */
+void CTimeEditDlg::accept()
+{
+ // Only commit here, cos dup keyframes will be deleted.
+ if (m_ObjectAssociation == ASSETKEYFRAME && m_Doc && m_KeyframesManager)
+ m_KeyframesManager->CommitChangedKeyframes();
+ else if (m_ObjectAssociation == TIMEBAR)
+ m_Callback->Commit();
+
+ QDialog::accept();
+}
+
+//==============================================================================
+/**
+ * reject: Upon clicking Cancel, revert to the initial time.
+ */
+void CTimeEditDlg::reject()
+{
+ // Only commit here, cos dup keyframes will be deleted.
+ if (m_ObjectAssociation == ASSETKEYFRAME && m_Doc && m_KeyframesManager)
+ m_KeyframesManager->RollbackChangedKeyframes();
+ else if (m_ObjectAssociation == TIMEBAR)
+ m_Callback->Rollback();
+ QDialog::reject();
+}
+
+//==============================================================================
+/**
+ * CountDigits: Counts the number of digits in a given number
+ * @param inNumber is the number that is used to count the number of digits
+ * @return the number of digits
+ */
+long CTimeEditDlg::CountDigits(long inNumber)
+{
+ long theNumberOfDigits = 0;
+ for (long theNumber = inNumber; theNumber >= 1; theNumber = theNumber / 10)
+ theNumberOfDigits++;
+ return theNumberOfDigits;
+}
+
+
+//==============================================================================
+/**
+ * TimeOverflowUnderflow: Checks if inMin, inSec or inMSec has exceeded the overflow/
+ * underflow limit. It will correct the time if it
+ *overflow/
+ * underflow.
+ * @param inMin stores the min segment of the time
+ * @param inSec stores the sec segment of the time
+ * @param inMSec stores the msec segment of the time
+ * @param inTimeLimit stores the time limit before the overflow/underflow occurs
+ * @param inOverflowOrUnderflow is set to true if we are checking for overflow else
+ * we are checking for underflow
+ * @returns true if overflow/underflow occurs, otherwise returns false.
+ */
+bool CTimeEditDlg::TimeOverflowUnderflow(long *inMin, long *inSec, long *inMSec, long inTimeLimit,
+ bool inOverflowOrUnderflow)
+{
+ // The codes below translates inTimeLimit into theLimitMin:theLimitSec:theLimitMsec
+ bool theLimitExceeds = false;
+ long theLimitMin;
+ long theLimitSec;
+ long theLimitMsec;
+ TimeConversion(inTimeLimit, &theLimitMin, &theLimitSec, &theLimitMsec,
+ CONVERT_MSEC_TO_MIN_SEC_MSEC);
+ // Handle time overflow/underflow
+ if ((*inMin > theLimitMin && inOverflowOrUnderflow)
+ || (*inMin < theLimitMin && inOverflowOrUnderflow == false)) // Minutes exceeds limit
+ {
+ // Set all time segments to the limit
+ *inMin = theLimitMin;
+ *inSec = theLimitSec;
+ *inMSec = theLimitMsec;
+ theLimitExceeds = true;
+ } else if (*inMin == theLimitMin) {
+ if ((*inSec > theLimitSec && inOverflowOrUnderflow)
+ || (*inSec < theLimitSec && inOverflowOrUnderflow == false)) // Seconds exceeds limit
+ {
+ // Set the Sec and Msec segments to the limit
+ *inSec = theLimitSec;
+ *inMSec = theLimitMsec;
+ theLimitExceeds = true;
+ } else if (*inSec == theLimitSec) {
+ if ((*inMSec > theLimitMsec && inOverflowOrUnderflow)
+ || (*inMSec < theLimitMsec
+ && inOverflowOrUnderflow == false)) // Milliseconds exceeds limit
+ {
+ // Msec segments to the limit
+ *inMSec = theLimitMsec;
+ theLimitExceeds = true;
+ }
+ }
+ }
+ return theLimitExceeds;
+}
+
+//==============================================================================
+/**
+ * TimeConversion: Converts inTime to the format specified by inFlags.
+ * For example:
+ * inTime = 5 sec inFlags = CONVERT_SEC_TO_MSEC
+ * The method will convert 5 sec into 5000 msec and
+ *returns
+ * the result.
+ * @param inTime stores the time to be converted.
+ * inOperationCode determines the type of time conversion to be done on the
+ * inTime.
+ * @return theResult stores the result of the time conversion.
+ */
+long CTimeEditDlg::TimeConversion(long inTime, long inOperationCode)
+{
+ long theResult = 0;
+ switch (inOperationCode) {
+ case CONVERT_MIN_TO_MSEC:
+ theResult = inTime * 60 * 1000;
+ break;
+ case CONVERT_SEC_TO_MSEC:
+ theResult = inTime * 1000;
+ break;
+ case CONVERT_MSEC_TO_MIN:
+ theResult = inTime / (60 * 1000);
+ break;
+ case CONVERT_MSEC_TO_SEC:
+ theResult = inTime / 1000;
+ break;
+ }
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * TimeConversion: Takes in the time in mins:secs:msec and convert it to
+ * the corresponding time in msec.
+ * @param inMin stores the minutes to be converted.
+ * inSec stores the seconds to be converted.
+ * inMsec stores the milliseconds to be converted.
+ * inOperationCode determines the type of time conversion to be done on the
+ * inMin, inSec and inMsec.
+ * @return theResult stores the result of the time conversion.
+ */
+long CTimeEditDlg::TimeConversion(long inMin, long inSec, long inMsec, long inOperationCode)
+{
+ long theResult = 0;
+ switch (inOperationCode) {
+ case CONVERT_TIME_TO_MSEC:
+ theResult = TimeConversion(inMin, CONVERT_MIN_TO_MSEC)
+ + TimeConversion(inSec, CONVERT_SEC_TO_MSEC) + inMsec;
+ break;
+ }
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * TimeConversion: Takes in the time in milliseconds and converts them
+ * to min : sec : msec.
+ * @param inTotalTime stores the total time in msec.
+ * ioMin stores the mins result of the time conversion
+ * ioSec stores the secs result of the time conversion
+ * ioMsec stores the msecs result of the time conversion
+ * inOperationCode determines the type of time conversion to be done on the
+ * inTotalTime.
+ * @return NONE
+ */
+void CTimeEditDlg::TimeConversion(long inTotalTime, long *ioMin, long *ioSec, long *ioMsec,
+ long inOperationCode)
+{
+ switch (inOperationCode) {
+ case CONVERT_MSEC_TO_MIN_SEC_MSEC:
+ *ioMin = TimeConversion(inTotalTime, CONVERT_MSEC_TO_MIN);
+ *ioSec = inTotalTime - TimeConversion(*ioMin, CONVERT_MIN_TO_MSEC);
+ *ioSec = TimeConversion(*ioSec, CONVERT_MSEC_TO_SEC);
+ *ioMsec = inTotalTime - TimeConversion(*ioMin, CONVERT_MIN_TO_MSEC)
+ - TimeConversion(*ioSec, CONVERT_SEC_TO_MSEC);
+ break;
+ }
+}
+//==============================================================================
+/**
+ * UpdateObjectTime: It updates the playhead, keyframe or timebar time according
+ * to the time displayed in the time edit dialogue.
+ * @param inTime is the time that will be updated.
+ * @param startTime if true, updates the start time on the object, otherwise the end time
+ * @return NONE
+ */
+void CTimeEditDlg::UpdateObjectTime(long inTime, bool startTime)
+{
+ long theDiff = 0;
+ switch (m_ObjectAssociation) {
+ case PLAYHEAD: // Update the playhead time
+ if (m_Doc) {
+ m_Doc->NotifyTimeChanged(inTime);
+ m_Doc->NotifyTimeChanged(inTime);
+ }
+ break;
+ case ASSETKEYFRAME: // Update the keyframe time
+ if (m_Doc) {
+ theDiff = inTime - m_OffsetFromInitialTime - m_InitialTime1;
+ m_OffsetFromInitialTime = m_OffsetFromInitialTime + theDiff;
+ if (theDiff != 0 && m_KeyframesManager) {
+ m_KeyframesManager->OffsetSelectedKeyframes(theDiff);
+ }
+ }
+ break;
+ case TIMEBAR: // Update the timebar start/end time
+ if (m_Callback) {
+ if (startTime) // Update Start Time
+ m_Callback->ChangeStartTime(inTime);
+ else // Update End Time
+ m_Callback->ChangeEndTime(inTime);
+ }
+ break;
+ }
+}
+
+//==============================================================================
+/** The codes methods below are provides platform independent wrappers for
+ * User Interface.
+ */
+//==============================================================================
+
+/**
+ * OnEnChangeTimeEdit: Event triggered when the text in the 1st time edit box has
+ * been changed.
+ * @param NONE
+ * @return NONE
+ */
+void CTimeEditDlg::OnEnChangeTimeEdit1()
+{
+ // Making sure that the start time is not greater than the end time, when
+ // the user modifies the start time of the timebar
+ if (m_ObjectAssociation == TIMEBAR) {
+ m_MaxTimeDisplay = m_InitialTime2; // the initial end time
+ }
+ m_MinTimeDisplay = 0;
+
+ const auto time = m_ui->startTimeEdit->time();
+ long min = time.minute() + time.hour() * 60;
+ long sec = time.second();
+ long msec = time.msec();
+ TimeOverflowUnderflow(&min, &sec, &sec, m_MaxTimeDisplay, true);
+ TimeOverflowUnderflow(&min, &sec, &msec, m_MinTimeDisplay, false);
+ if (min != time.minute() || sec != time.second() ||
+ msec != time.msec()) {
+ m_ui->startTimeEdit->setTime(QTime(0, min, sec, msec));
+ }
+ m_ui->startTimeMin->setText(QString::number(min));
+ m_ui->startTimeSec->setText(QString::number(sec));
+ m_ui->startTimeMsec->setText(QString::number(msec));
+
+ long theGoToTime = TimeConversion(min, CONVERT_MIN_TO_MSEC)
+ + TimeConversion(sec, CONVERT_SEC_TO_MSEC) + msec;
+ // Go to the time specified in the time edit display
+ UpdateObjectTime(theGoToTime, true /*start time*/);
+}
+
+//==============================================================================
+/**
+ * OnEnChangeTimeEdit2: Event triggered when the text in the 2nd time edit box has
+ * been changed.
+ * @param NONE
+ * @return NONE
+ */
+void CTimeEditDlg::OnEnChangeTimeEdit2()
+{
+ // Let the end time of the time bar go as far as possible
+ if (m_ObjectAssociation == TIMEBAR) {
+ m_MaxTimeDisplay = m_MaxTime;
+ m_MinTimeDisplay = m_InitialTime1; // the initial start time
+ }
+ const auto time = m_ui->endTimeEdit->time();
+ long min = time.minute() + time.hour() * 60;
+ long sec = time.second();
+ long msec = time.msec();
+ TimeOverflowUnderflow(&min, &sec, &sec, m_MaxTimeDisplay, true);
+ TimeOverflowUnderflow(&min, &sec, &msec, m_MinTimeDisplay, false);
+ if (min != time.minute() || sec != time.second() ||
+ msec != time.msec()) {
+ m_ui->endTimeEdit->setTime(QTime(0, min, sec, msec));
+ }
+ m_ui->endTimeMin->setText(QString::number(min));
+ m_ui->endTimeSec->setText(QString::number(sec));
+ m_ui->endTimeMsec->setText(QString::number(msec));
+
+ long theGoToTime = TimeConversion(min, CONVERT_MIN_TO_MSEC)
+ + TimeConversion(sec, CONVERT_SEC_TO_MSEC) + msec;
+ // Go to the time specified in the time edit display
+ UpdateObjectTime(theGoToTime, false /*end time*/);
+}
+
+
+//==============================================================================
+/**
+ * HideUnnecessaryFields: Hides unused dialog items
+ * @param NONE
+ * @return NONE
+ */
+void CTimeEditDlg::HideUnnecessaryFields()
+{
+ m_ui->endTimeGroup->hide();
+ m_ui->startTimeLabel->hide();
+}
+
diff --git a/src/Authoring/Studio/_Win/UI/TimeEditDlg.h b/src/Authoring/Studio/_Win/UI/TimeEditDlg.h
new file mode 100644
index 00000000..7103dd3e
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/TimeEditDlg.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+
+#ifndef INCLUDED_TIME_EDIT_DIALOG_H
+#define INCLUDED_TIME_EDIT_DIALOG_H 1
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Dialogs.h"
+#include <QDialog>
+#include <QDateTimeEdit>
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CTimebarControl;
+class IDoc;
+class ITimelineKeyframesManager;
+
+//==============================================================================
+// Defines
+//==============================================================================
+
+enum ECursorPosition { MIN_POSITION, SEC_POSITION, MSEC_POSITION };
+
+enum ETimeFormat { MSEC, SEC_MSEC, MIN_SEC_MSEC };
+
+enum ETimeConversionOperation {
+ CONVERT_MIN_TO_MSEC,
+ CONVERT_SEC_TO_MSEC,
+ CONVERT_MSEC_TO_MIN,
+ CONVERT_MSEC_TO_SEC,
+ CONVERT_TIME_TO_MSEC,
+ CONVERT_MSEC_TO_MIN_SEC_MSEC
+};
+
+enum ETimeEditBoxNumber { EDITBOX1, EDITBOX2 };
+
+enum EObjectAssociation {
+ PLAYHEAD,
+ ASSETKEYFRAME,
+ TIMEBAR,
+};
+
+class ITimeChangeCallback
+{
+public:
+ virtual ~ITimeChangeCallback() {}
+ virtual void ChangeStartTime(long) = 0;
+ virtual void ChangeEndTime(long) = 0;
+ virtual void Commit() = 0;
+ virtual void Rollback() = 0;
+};
+
+#ifdef QT_NAMESPACE
+using namespace QT_NAMESPACE;
+#endif
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class TimeEditDlg;
+}
+QT_END_NAMESPACE
+
+// This class workaround the problem of QDateTimeEdit overwriting the selected section
+// See https://bugreports.qt.io/browse/QTBUG-34759
+class CDateTimeEdit : public QDateTimeEdit
+{
+ Q_OBJECT
+public:
+ using QDateTimeEdit::QDateTimeEdit;
+
+protected:
+ void focusInEvent(QFocusEvent *event) {
+ QDateTimeEdit::focusInEvent(event);
+ setSelectedSection(QDateTimeEdit::SecondSection);
+ }
+};
+
+//==============================================================================
+/**
+ * CTimeEditDlg: It is a dialog box that allows user to specify the time that
+ * he/she wishes to go to. This dialog box can be activated by
+ * pressing Control G or clicking on the time edit box in the
+ * timeline.
+ */
+//==============================================================================
+class CTimeEditDlg : public QDialog
+{
+ Q_OBJECT
+
+public:
+ CTimeEditDlg(QWidget *pParent = nullptr); // standard constructor
+ virtual ~CTimeEditDlg();
+ void SetKeyframesManager(ITimelineKeyframesManager *inKeyframeManager);
+ void ShowDialog(long inTime1, long inTime2, IDoc *inDoc, long inObjectAssociation,
+ ITimeChangeCallback *inCallback = nullptr);
+
+public Q_SLOTS:
+ void accept() override;
+ void reject() override;
+
+protected:
+ void showEvent(QShowEvent *) override;
+
+ // Generated message map functions
+ void OnInitDialog();
+ void OnEnChangeTimeEdit1();
+ void OnEnChangeTimeEdit2();
+
+ QString FormatTime(long inTime);
+ long CountDigits(long inNumber);
+ long TimeConversion(long inTime, long inOperationCode);
+ long TimeConversion(long inMin, long inSec, long inMsec, long inOperationCode);
+ void TimeConversion(long inTotalTime, long *ioMin, long *ioSec, long *ioMsec,
+ long inOperationCode);
+ void UpdateObjectTime(long inTime, bool startTime);
+ bool TimeOverflow(long *inMin, long *inSec, long *inMSec, long inTimeLimit);
+ bool TimeOverflowUnderflow(long *inMin, long *inSec, long *inMSec, long inTimeLimit,
+ bool inOverflowOrUnderflow);
+ void HideUnnecessaryFields();
+
+protected:
+ QString m_MinString;
+ QString m_SecString;
+ QString m_MSecString;
+ QString m_TimeDisplay1;
+ QString m_TimeDisplay2;
+ long m_MaxTime;
+ long m_MaxTimeDisplay;
+ long m_MinTimeDisplay;
+ long m_InitialTime1;
+ long m_InitialTime2;
+ long m_MinOffset;
+ long m_SecOffset;
+ long m_MSecOffset;
+ long m_MinMinorOffset;
+ long m_SecMinorOffset;
+ long m_MSecMinorOffset;
+ long m_CursorPosition;
+ long m_TimeFormat;
+ long m_PreviousFormat;
+ double m_TimeInMins;
+ long m_NumberOfDigitsDrop;
+ long m_ColonPosition1;
+ long m_ColonPosition2;
+ long m_ObjectAssociation;
+ long m_OffsetFromInitialTime;
+ QString m_DTime;
+ QString m_DTimeDisplay;
+ long m_Time1;
+ long m_Time2;
+ IDoc *m_Doc;
+ ITimelineKeyframesManager *m_KeyframesManager;
+
+ ITimeChangeCallback *m_Callback;
+ Ui::TimeEditDlg *m_ui;
+};
+#endif // INCLUDED_TIME_EDIT_DIALOG_H
diff --git a/src/Authoring/Studio/_Win/UI/timeeditdlg.ui b/src/Authoring/Studio/_Win/UI/timeeditdlg.ui
new file mode 100644
index 00000000..f46cb1a2
--- /dev/null
+++ b/src/Authoring/Studio/_Win/UI/timeeditdlg.ui
@@ -0,0 +1,364 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TimeEditDlg</class>
+ <widget class="QDialog" name="TimeEditDlg">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>371</width>
+ <height>274</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Go To Time</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="startTimeGroup" native="true">
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="2" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="CDateTimeEdit" name="startTimeEdit">
+ <property name="currentSection">
+ <enum>QDateTimeEdit::SecondSection</enum>
+ </property>
+ <property name="displayFormat">
+ <string>hh:mm:ss:zzz</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="1" column="1">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="startTimeMin">
+ <property name="text">
+ <string>00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>sec</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="startTimeSec">
+ <property name="text">
+ <string>00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>min</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="4">
+ <widget class="QLabel" name="startTimeMsec">
+ <property name="text">
+ <string>000</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="startTimeLabel">
+ <property name="text">
+ <string>Start Time</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="endTimeGroup" native="true">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="endTimeLabel">
+ <property name="text">
+ <string>End Time</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="CDateTimeEdit" name="endTimeEdit">
+ <property name="currentSection">
+ <enum>QDateTimeEdit::SecondSection</enum>
+ </property>
+ <property name="displayFormat">
+ <string>hh:mm:ss:zzz</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="1" column="1">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="endTimeMin">
+ <property name="text">
+ <string>00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="label_11">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_12">
+ <property name="text">
+ <string>sec</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="endTimeSec">
+ <property name="text">
+ <string>00</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_14">
+ <property name="text">
+ <string>min</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="4">
+ <widget class="QLabel" name="endTimeMsec">
+ <property name="text">
+ <string>000</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QLabel" name="label_16">
+ <property name="text">
+ <string>:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_7">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>CDateTimeEdit</class>
+ <extends>QTimeEdit</extends>
+ <header>TimeEditDlg.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>TimeEditDlg</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>TimeEditDlg</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/Authoring/Studio/_Win/Utils/MouseCursor.cpp b/src/Authoring/Studio/_Win/Utils/MouseCursor.cpp
new file mode 100644
index 00000000..9cd7328d
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Utils/MouseCursor.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+// WIN32 VERSION
+
+//=============================================================================
+// Prefix
+//=============================================================================
+#include "stdafx.h"
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "MouseCursor.h"
+#include <QPixmap>
+#include <QDebug>
+
+//#ifdef WIN32
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ARROW = 0; // IDC_ARROW
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_WAIT = 1; // IDC_WAIT
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_RESIZE_LEFTRIGHT = 2; // IDC_SIZEWE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_RESIZE_UPDOWN = 3; // IDC_SIZENS
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_GROUP_MOVE = 4; // IDC_GROUP_MOVE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_GROUP_ROTATE = 5; // IDC_GROUP_ROTATE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_GROUP_SCALE = 6; // IDC_GROUP_SCALE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ITEM_MOVE = 7; // IDC_ITEM_MOVE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ITEM_ROTATE = 8; // IDC_ITEM_ROTATE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ITEM_SCALE = 9; // IDC_ITEM_SCALE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_EDIT_CAMERA_PAN =
+ 10; // IDC_EDIT_CAMERA_PAN
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_EDIT_CAMERA_ROTATE =
+ 11; // IDC_EDIT_CAMERA_ROTATE
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_EDIT_CAMERA_ZOOM =
+ 12; // IDC_EDIT_CAMERA_ZOOM
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_BLANK = 13; // blank cursor
+const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_IBEAM = 14;
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CMouseCursor::CMouseCursor()
+ : m_IsThemeCursor(false)
+ , m_ThemeCursor(-1)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CMouseCursor::~CMouseCursor()
+{
+ Destroy();
+}
+
+//=============================================================================
+/**
+ * @return A platform-specific handle to the cursor, or nullptr if no cursor has been loaded
+ */
+QCursor CMouseCursor::GetHandle()
+{
+ return m_Handle;
+}
+
+//=============================================================================
+/**
+ * If a cursor has been loaded, this function will change the current cursor
+ * to the newly loaded one.
+ */
+void CMouseCursor::Show()
+{
+ qWarning() << Q_FUNC_INFO << "QCursor doesn't work this way - set a breakpoint and debug caller";
+}
+
+//=============================================================================
+/**
+* Sets the cursor position
+* @param inXPos x position of the cursor (in pixels)
+* @param inYPos y position of the cursor (in pixels)
+*/
+void CMouseCursor::SetCursorPos(long inXPos, long inYPos)
+{
+ QCursor::setPos(QPoint(inXPos, inYPos));
+}
+
+//=============================================================================
+/**
+ * Releases the cursor if one has been loaded. Called by the destructor.
+ * WINDOWS IMPLEMENTATION
+ */
+void CMouseCursor::Destroy()
+{
+}
+
+//=============================================================================
+/**
+ * Loads the specified cursor resource. All cursors are expected to be
+ * resources that are loaded from ".cur" files. Some standard cursors are
+ * defined by the system and can be found in the MSDN (IDC_ARROW for example).
+ * WINDOWS IMPLEMENTATION
+ *
+ * @param inCursor ID of the cursor to be loaded
+ * @return true if the cursor was successfully loaded, otherwise false
+ */
+bool CMouseCursor::Load(TUICMouseCursor inCursor)
+{
+ // Convert from our cursors to Windows specific cursors
+ switch (inCursor) {
+ case CURSOR_ARROW:
+ m_Handle = Qt::ArrowCursor;
+ break;
+
+ case CURSOR_WAIT:
+ m_Handle = Qt::WaitCursor;
+ break;
+
+ case CURSOR_RESIZE_LEFTRIGHT:
+ m_Handle = Qt::SizeHorCursor;
+ break;
+
+ case CURSOR_RESIZE_UPDOWN:
+ m_Handle = Qt::SizeVerCursor;
+ break;
+
+ case CURSOR_GROUP_MOVE:
+ m_Handle = QCursor(QPixmap(":/cursors/group_move.png"), 0, 0);
+ break;
+
+ case CURSOR_GROUP_ROTATE:
+ m_Handle = QCursor(QPixmap(":/cursors/group_rotate.png"), 0, 0);
+ break;
+
+ case CURSOR_GROUP_SCALE:
+ m_Handle = QCursor(QPixmap(":/cursors/group_scale.png"), 0, 0);
+ break;
+
+ case CURSOR_ITEM_MOVE:
+ m_Handle = QCursor(QPixmap(":/cursors/item_move.png"), 0, 0);
+ break;
+
+ case CURSOR_ITEM_ROTATE:
+ m_Handle = QCursor(QPixmap(":/cursors/item_rotate.png"), 0, 0);
+ break;
+
+ case CURSOR_ITEM_SCALE:
+ m_Handle = QCursor(QPixmap(":/cursors/item_scale.png"), 0, 0);
+ break;
+
+ case CURSOR_EDIT_CAMERA_PAN:
+ m_Handle = QCursor(QPixmap(":/cursors/edit_camera_pan.png"), 10, 10);
+ break;
+
+ case CURSOR_EDIT_CAMERA_ROTATE:
+ m_Handle = QCursor(QPixmap(":/cursors/edit_camera_rot.png"), 8, 10);
+ break;
+
+ case CURSOR_EDIT_CAMERA_ZOOM:
+ m_Handle = QCursor(QPixmap(":/cursors/edit_camera_zoom.png"), 8, 8);
+ break;
+
+ case CURSOR_BLANK:
+ m_Handle = Qt::BlankCursor;
+ break;
+ case CURSOR_IBEAM:
+ m_Handle = Qt::IBeamCursor;
+ break;
+ default:
+ m_Handle = QCursor();
+ break;
+ }
+ return true;
+}
diff --git a/src/Authoring/Studio/_Win/Utils/WinUtils.cpp b/src/Authoring/Studio/_Win/Utils/WinUtils.cpp
new file mode 100644
index 00000000..e159fa12
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Utils/WinUtils.cpp
@@ -0,0 +1,600 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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 "stdafx.h"
+#include "Strings.h"
+
+#include "WinUtils.h"
+
+//==============================================================================
+/**
+ * DrawBitmap
+ *
+ * Draw a bitmap given a device context, position and HBITMAP handle.
+ *
+ * @param inDC Device context for drawing
+ * @param inPos CPoint position for drawing
+ * @param inBitmap Handle of the bitmap to draw
+ */
+//==============================================================================
+void CWinUtils::DrawBitmap(CDC *inDC, CPoint inPos, HBITMAP inBitmap)
+{
+ CDC theMemDC;
+ BITMAP theBitmapStruct;
+ CBitmap *theOldBitmap;
+
+ if ((inDC != nullptr) && (inBitmap != nullptr)) {
+ GetObject(inBitmap, sizeof(BITMAP), &theBitmapStruct);
+
+ theMemDC.CreateCompatibleDC(inDC);
+ theOldBitmap = theMemDC.SelectObject(CBitmap::FromHandle(inBitmap));
+
+ inDC->BitBlt(inPos.x, inPos.y, theBitmapStruct.bmWidth, theBitmapStruct.bmHeight, &theMemDC,
+ 0, 0, SRCCOPY);
+
+ theMemDC.SelectObject(theOldBitmap);
+ theMemDC.DeleteDC();
+ }
+}
+
+//==============================================================================
+/**
+ * DrawTransparentBitmap
+ *
+ * Draw a bitmap given a device context, position and HBITMAP handle using transparency
+ *
+ * @param inDC Device context for drawing
+ * @param inDestX Destination X position
+ * @param inDestY Destination Y position
+ * @param inBmp Bitmap for drawing
+ * @param inColorTransparent Transparent color
+ * @param inWidth Destination width
+ * @param inHeight Destination height
+ * @param inSourceX Source X position
+ * @param inSourceY Source Y position
+ */
+//==============================================================================
+void CWinUtils::DrawTransparentBitmap(CDC *inDC, long inDestX, long inDestY, HBITMAP inBmp,
+ COLORREF inColorTransparent, long inWidth, long inHeight,
+ long inSourceX, long inSourceY)
+{
+ CDC theMemDC;
+ BITMAP theBitmap;
+ CBitmap *theOldBmp;
+
+ GetObject(inBmp, sizeof(BITMAP), &theBitmap);
+
+ if (inWidth == -1)
+ inWidth = theBitmap.bmWidth;
+ if (inHeight == -1)
+ inHeight = theBitmap.bmHeight;
+
+ theMemDC.CreateCompatibleDC(inDC);
+ theOldBmp = theMemDC.SelectObject(CBitmap::FromHandle(inBmp));
+
+ TransparentBltExt(inDC->m_hDC, inDestX, inDestY, inWidth, inHeight, theMemDC.m_hDC, inSourceX,
+ inSourceY, inWidth, inHeight, inColorTransparent);
+
+ theMemDC.SelectObject(theOldBmp);
+ theMemDC.DeleteDC();
+}
+
+//==============================================================================
+/**
+ * TransparentBltExt
+ *
+ * Draw a bitmap given a device context, position and HBITMAP handle using transparency
+ *
+ * @param inDC Device context for drawing
+ * @param inDestX Destination X position
+ * @param inDestY Destination Y position
+ * @param inBmp Bitmap for drawing
+ * @param inColorTransparent Transparent color
+ * @param inWidth Destination width
+ * @param inHeight Destination height
+ * @param inSourceX Source X position
+ * @param inSourceY Source Y position
+ */
+//==============================================================================
+BOOL CWinUtils::TransparentBltExt(HDC inDCDest, long inXOriginDest, long inYOriginDest,
+ long inWidthDest, long inHeightDest, HDC inDCSrc,
+ long inXOriginSrc, long inYOriginSrc, long inWidthSrc,
+ long inHeightSrc, UINT inColorTransparent)
+{
+ if ((inWidthDest < 1) || (inWidthSrc < 1) || (inHeightDest < 1) || (inHeightSrc < 1))
+ return FALSE;
+
+ HDC theDC, theMaskDC;
+ HDC theNewMaskDC;
+ HBITMAP theBmp, theOldBmp, theMaskBmp, theOldMask;
+ HBITMAP theNewMask;
+
+ theDC = CreateCompatibleDC(nullptr);
+ theBmp = CreateBitmap(inWidthSrc, inHeightSrc, 1, GetDeviceCaps(theDC, BITSPIXEL), nullptr);
+
+ if (theBmp == nullptr) {
+ DeleteDC(theDC);
+ return FALSE;
+ }
+
+ theOldBmp = (HBITMAP)SelectObject(theDC, theBmp);
+
+ if (!BitBlt(theDC, 0, 0, inWidthSrc, inHeightSrc, inDCSrc, inXOriginSrc, inYOriginSrc,
+ SRCCOPY)) {
+ SelectObject(theDC, theOldBmp);
+ DeleteObject(theBmp);
+ DeleteDC(theDC);
+ return FALSE;
+ }
+
+ theMaskDC = CreateCompatibleDC(nullptr);
+ theMaskBmp = CreateBitmap(inWidthSrc, inHeightSrc, 1, 1, nullptr);
+
+ if (theMaskBmp == nullptr) {
+ SelectObject(theDC, theOldBmp);
+ DeleteObject(theBmp);
+ DeleteDC(theDC);
+ DeleteDC(theMaskDC);
+ return FALSE;
+ }
+
+ theOldMask = (HBITMAP)SelectObject(theMaskDC, theMaskBmp);
+ SetBkColor(theMaskDC, RGB(0x00, 0x00, 0x00));
+ SetTextColor(theMaskDC, RGB(0xFF, 0xFF, 0xFF));
+
+ if (!BitBlt(theMaskDC, 0, 0, inWidthSrc, inHeightSrc, nullptr, 0, 0, BLACKNESS)) {
+ SelectObject(theMaskDC, theOldMask);
+ DeleteObject(theMaskBmp);
+ DeleteDC(theMaskDC);
+ SelectObject(theDC, theOldBmp);
+ DeleteObject(theBmp);
+ DeleteDC(theDC);
+ return FALSE;
+ }
+
+ SetBkColor(theDC, inColorTransparent);
+ BitBlt(theMaskDC, 0, 0, inWidthSrc, inHeightSrc, theDC, 0, 0, SRCINVERT);
+
+ SetBkColor(theDC, RGB(0x00, 0x00, 0x00));
+ SetTextColor(theDC, RGB(0xFF, 0xFF, 0xFF));
+ BitBlt(theDC, 0, 0, inWidthSrc, inHeightSrc, theMaskDC, 0, 0, SRCAND);
+
+ theNewMaskDC = CreateCompatibleDC(nullptr);
+ theNewMask =
+ CreateBitmap(inWidthDest, inHeightDest, 1, GetDeviceCaps(theNewMaskDC, BITSPIXEL), nullptr);
+ if (theNewMask == nullptr) {
+ SelectObject(theDC, theOldBmp);
+ DeleteDC(theDC);
+ SelectObject(theMaskDC, theOldMask);
+ DeleteDC(theMaskDC);
+ DeleteDC(theNewMaskDC);
+ DeleteObject(theBmp);
+ DeleteObject(theMaskBmp);
+ return FALSE;
+ }
+
+ SetStretchBltMode(theNewMaskDC, COLORONCOLOR);
+ HBITMAP theOldNewMask = (HBITMAP)SelectObject(theNewMaskDC, theNewMask);
+ StretchBlt(theNewMaskDC, 0, 0, inWidthDest, inHeightDest, theMaskDC, 0, 0, inWidthSrc,
+ inHeightSrc, SRCCOPY);
+
+ SelectObject(theMaskDC, theOldMask);
+ DeleteDC(theMaskDC);
+ DeleteObject(theMaskBmp);
+
+ HDC theNewImageDC = CreateCompatibleDC(nullptr);
+ HBITMAP theNewImage =
+ CreateBitmap(inWidthDest, inHeightDest, 1, GetDeviceCaps(theNewMaskDC, BITSPIXEL), nullptr);
+ if (theNewImage == nullptr) {
+ SelectObject(theDC, theOldBmp);
+ DeleteDC(theDC);
+ DeleteDC(theNewMaskDC);
+ DeleteObject(theBmp);
+ return FALSE;
+ }
+
+ HBITMAP theOldNewImage = (HBITMAP)SelectObject(theNewImageDC, theNewImage);
+ StretchBlt(theNewImageDC, 0, 0, inWidthDest, inHeightDest, theDC, 0, 0, inWidthSrc, inHeightSrc,
+ SRCCOPY);
+
+ SelectObject(theDC, theOldBmp);
+ DeleteDC(theDC);
+ DeleteObject(theBmp);
+
+ // Finally, do the final blitting to get the image to the destination device context.
+ BitBlt(inDCDest, inXOriginDest, inYOriginDest, inWidthDest, inHeightDest, theNewMaskDC, 0, 0,
+ SRCAND);
+ BitBlt(inDCDest, inXOriginDest, inYOriginDest, inWidthDest, inHeightDest, theNewImageDC, 0, 0,
+ SRCPAINT);
+
+ SelectObject(theNewImageDC, theOldNewImage);
+ DeleteDC(theNewImageDC);
+ SelectObject(theNewMaskDC, theOldNewMask);
+ DeleteDC(theNewMaskDC);
+ DeleteObject(theNewImage);
+ DeleteObject(theNewMask);
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * DrawAlphaBlendBitmap
+ *
+ * Draw a bitmap given a device context, position and HBITMAP handle using
+ * alpha blending and transparency.
+ *
+ * @param inDC Device context for drawing
+ * @param inDestX Destination X position
+ * @param inDestY Destination Y position
+ * @param inBmp Bitmap for drawing
+ * @param inColorTransparent Transparent color
+ * @param inWidth Destination width
+ * @param inHeight Destination height
+ * @param inSourceX Source X position
+ * @param inSourceY Source Y position
+ */
+//==============================================================================
+void CWinUtils::DrawAlphaBlendBitmap(CDC *inDC, short inDestX, short inDestY, HBITMAP inBmp,
+ short inWidth, short inHeight, short inSourceX,
+ short inSourceY, short inAlpha, BOOL inTransparentFlag,
+ COLORREF inColorTransparent)
+{
+ Q_UNUSED(inColorTransparent);
+
+ CDC theMemDC;
+ BITMAP theBitmap;
+ CBitmap *theOldBmp;
+ short theWidth = inWidth;
+ short theHeight = inHeight;
+
+ COLORREF theBackColor;
+
+ // Get the size of the bitmap.
+ GetObject(inBmp, sizeof(BITMAP), &theBitmap);
+
+ if (inWidth == -1)
+ theWidth = (short)theBitmap.bmWidth;
+ if (inHeight == -1)
+ theHeight = (short)theBitmap.bmHeight;
+
+ theMemDC.CreateCompatibleDC(inDC);
+ theOldBmp = theMemDC.SelectObject(CBitmap::FromHandle(inBmp));
+
+ if (inTransparentFlag) {
+ // Get the current background pixel at 0,0
+ theBackColor = theMemDC.GetPixel(0, 0);
+
+ // Create a fill brush and select into the device context
+ CBrush theFillBrush(inColorTransparent);
+ CBrush *theOldFillBrush;
+
+ // Fill to replace the existing background color with the replacement color.
+ theOldFillBrush = theMemDC.SelectObject(&theFillBrush);
+ theMemDC.ExtFloodFill(0, 0, theBackColor, FLOODFILLSURFACE);
+ theMemDC.ExtFloodFill(theWidth - 1, 0, theBackColor, FLOODFILLSURFACE);
+ theMemDC.ExtFloodFill(theWidth - 1, theHeight - 1, theBackColor, FLOODFILLSURFACE);
+ theMemDC.ExtFloodFill(0, theHeight - 1, theBackColor, FLOODFILLSURFACE);
+ theMemDC.SelectObject(theOldFillBrush);
+ }
+
+ // Draw the alpha-blended image.
+ AlphaBlendExt(inDC->m_hDC, inDestX, inDestY, theWidth, theHeight, theMemDC.m_hDC, inSourceX,
+ inSourceY, theWidth, theHeight, inAlpha);
+
+ theMemDC.SelectObject(theOldBmp);
+ theMemDC.DeleteDC();
+}
+
+//==============================================================================
+/**
+ * AlphaBlendExt
+ *
+ * Draws a bitmap using alpha blending. Works in NT/2000/9x
+ *
+ * @param inDCDest Destination device context
+ * @param inX X coordinate for drawing
+ * @param inY Y coordinate for drawing
+ * @param inWidth Drawing width
+ * @param inHeight Drawing height
+ * @param inDCSrc Source device context
+ * @param inSourceX X source coordinate
+ * @param inSourceY Y source coordinate
+ * @param inSourceWidth Source drawing width
+ * @param inSourceHeight Source drawing height
+ * @param inAlpha Alpha blend: 0-255, where 255 is opaque
+ */
+//==============================================================================
+BOOL CWinUtils::AlphaBlendExt(HDC inDCDest, short inX, short inY, short inWidth, short inHeight,
+ HDC inDCSrc, short inSourceX, short inSourceY, short inSourceWidth,
+ short inSourceHeight, short inAlpha)
+{
+ BITMAPINFOHEADER theBMI;
+
+ theBMI.biSize = sizeof(BITMAPINFOHEADER);
+ theBMI.biWidth = inWidth;
+ theBMI.biHeight = inHeight;
+ theBMI.biPlanes = 1;
+ theBMI.biBitCount = 32; // 24 bits + alpha channel
+ theBMI.biCompression = BI_RGB; // no compression
+ theBMI.biSizeImage = 0;
+ theBMI.biXPelsPerMeter = 0;
+ theBMI.biYPelsPerMeter = 0;
+ theBMI.biClrUsed = 0; // use the whole palette
+ theBMI.biClrImportant = 0;
+
+ BYTE *theSrcBits;
+ HBITMAP theBmpSrc;
+
+ // Create DIB section in shared memory
+ theBmpSrc = CreateDIBSection(inDCSrc, (BITMAPINFO *)&theBMI, DIB_RGB_COLORS,
+ (void **)&theSrcBits, 0, 0L);
+
+ BYTE *theDestBits;
+ HBITMAP theBmpDest;
+
+ // Create DIB section in shared memory
+ theBmpDest = CreateDIBSection(inDCDest, (BITMAPINFO *)&theBMI, DIB_RGB_COLORS,
+ (void **)&theDestBits, 0, 0L);
+
+ // Copy our source and destination bitmaps onto our DIBSections.
+ // so we can get access to their bits using the BYTE*'s we used
+ // in the CreateDIBSection()s above.
+
+ HDC theDC = CreateCompatibleDC(nullptr);
+ HBITMAP theDCOld = (HBITMAP)SelectObject(theDC, theBmpSrc);
+
+ if (!StretchBlt(theDC, 0, 0, inWidth, inHeight, inDCSrc, inSourceX, inSourceY, inSourceWidth,
+ inSourceHeight, SRCCOPY)) {
+ SelectObject(theDC, theDCOld);
+ DeleteDC(theDC);
+ DeleteObject(theBmpSrc);
+ DeleteObject(theBmpDest);
+ return FALSE;
+ }
+
+ SelectObject(theDC, theBmpDest);
+
+ if (!StretchBlt(theDC, 0, 0, inWidth, inHeight, inDCDest, inX, inY, inWidth, inHeight,
+ SRCCOPY)) {
+ SelectObject(theDC, theDCOld);
+ DeleteDC(theDC);
+ DeleteObject(theBmpSrc);
+ DeleteObject(theBmpDest);
+ return FALSE;
+ }
+
+ SelectObject(theDC, theDCOld);
+ DeleteDC(theDC);
+
+ short theXLoop, theYLoop;
+
+ for (theYLoop = 0; theYLoop < inHeight; ++theYLoop) {
+ LPBYTE theDestRGB = (LPBYTE) & ((DWORD *)theDestBits)[theYLoop * inWidth];
+ LPBYTE theSrcRGB = (LPBYTE) & ((DWORD *)theSrcBits)[theYLoop * inWidth];
+
+ for (theXLoop = 0; theXLoop < inWidth; theXLoop++) {
+ theSrcRGB[0] = (BYTE)((theDestRGB[0] * (255 - inAlpha) + theSrcRGB[0] * inAlpha) >> 8);
+ theSrcRGB[1] = (BYTE)((theDestRGB[1] * (255 - inAlpha) + theSrcRGB[1] * inAlpha) >> 8);
+ theSrcRGB[2] = (BYTE)((theDestRGB[2] * (255 - inAlpha) + theSrcRGB[2] * inAlpha) >> 8);
+
+ theSrcRGB += 4;
+ theDestRGB += 4;
+ }
+ }
+
+ theDC = CreateCompatibleDC(nullptr);
+
+ theDCOld = (HBITMAP)SelectObject(theDC, theBmpSrc);
+
+ if (!BitBlt(inDCDest, inX, inY, inWidth, inHeight, theDC, 0, 0, SRCCOPY)) {
+ SelectObject(theDC, theDCOld);
+ DeleteDC(theDC);
+ DeleteObject(theBmpSrc);
+ DeleteObject(theBmpDest);
+ return FALSE;
+ }
+
+ SelectObject(theDC, theDCOld);
+ DeleteDC(theDC);
+
+ DeleteObject(theBmpSrc);
+ DeleteObject(theBmpDest);
+
+ return TRUE;
+}
+
+//==============================================================================
+/**
+ * GetStudioLogFont: Fill a LOGFONT structure with the default font information for Studio
+ *objects.
+ *
+ * Create a LOGFONT structure with data used by the various palettes and controls in Studio.
+ *
+ * @param outLogFont LOGFONT structure returned by this function.
+ */
+//==============================================================================
+void CWinUtils::GetStudioLogFont(LOGFONT &outLogFont)
+{
+ // Create the default Studio font - specified in string table so that it can be changed for
+ // different languages
+ memset(&outLogFont, 0, sizeof(LOGFONT));
+ CString theFontSize = ::LoadResourceString(IDS_STUDIOFONT_SIZE);
+ CString theFontFace = L"SegoeUI";
+ outLogFont.lfHeight = _wtoi(theFontSize);
+ wcscpy(outLogFont.lfFaceName, theFontFace);
+ // Make sure that you set the character set to the system default or your strings won't be
+ // localizable
+ outLogFont.lfCharSet = DEFAULT_CHARSET;
+}
+
+//=============================================================================
+/**
+ * Copy the contents of a File into an Archive.
+ * This will read the entire file into the archive.
+ * The file should exist already.
+ * @param inFilename the name of the file to read in.
+ * @param inDestination the destination archive for the data.
+ */
+//=============================================================================
+void CWinUtils::CopyFileToArchive(CString inFilename, CArchive &inDestination)
+{
+ CFile theFile(inFilename, CFile::modeRead);
+
+ unsigned long theLength = (unsigned long)theFile.GetLength();
+ unsigned long theBufferSize = 1024;
+ while (theBufferSize < theLength / 10 && theBufferSize < 1e6)
+ theBufferSize *= 2; // double until we have a buffer that is about %10 of file size
+ char *theBuffer = new char[theBufferSize];
+
+ unsigned long theReadCount = theBufferSize;
+ unsigned long theTotalReadCount = 0;
+
+ // Loop around reading the file in chunks
+ while (theTotalReadCount < theLength) {
+ if (theLength - theTotalReadCount < theReadCount)
+ theReadCount = theLength - theTotalReadCount;
+
+ theFile.Read(theBuffer, theReadCount);
+ inDestination.Write(theBuffer, theReadCount);
+
+ theTotalReadCount += theReadCount;
+ }
+
+ theFile.Close();
+ delete[] theBuffer;
+}
+
+//=============================================================================
+/**
+ * Copy the contents of an Archive into a File.
+ * If the file does not exist it will be created. If it does exist it will be
+ * cleared.
+ * @param inArchive the source of the data for the file.
+ * @param inDestination the file the data is to be written to.
+ * @param inLength the amount of data to copy to the file.
+ */
+//=============================================================================
+void CWinUtils::CopyArchiveToFile(CArchive &inArchive, CString inDestination,
+ unsigned long inLength)
+{
+ CFile theFile(inDestination, CFile::modeWrite | CFile::modeCreate);
+
+ unsigned long theBufferSize = 1024;
+ while (theBufferSize < inLength / 10 && theBufferSize < 1e6)
+ theBufferSize *= 2; // double until we have a buffer that is about %10 of file size
+ char *theBuffer = new char[theBufferSize];
+
+ unsigned long theLength = inLength;
+ unsigned long theReadCount = theBufferSize;
+ unsigned long theTotalReadCount = 0;
+
+ // Loop around reading from the archive and writing to the file.
+ while (theTotalReadCount < theLength) {
+ if (theLength - theTotalReadCount < theReadCount)
+ theReadCount = theLength - theTotalReadCount;
+
+ inArchive.Read(theBuffer, theReadCount);
+ theFile.Write(theBuffer, theReadCount);
+
+ theTotalReadCount += theReadCount;
+ }
+ theFile.Close();
+ delete[] theBuffer;
+}
+
+//=============================================================================
+/**
+ * Used for StringToInt64 to avoid double errors in math.h's pow( ).
+ *
+ * @param inNumber Base number
+ * @param inPower Power to raise the base
+ *
+ * @return Result of x^y
+ */
+//=============================================================================
+unsigned __int64 CWinUtils::RaisePower(unsigned __int64 inNumber, unsigned long inPower)
+{
+ if (inPower == 0)
+ return 1;
+ return inNumber * RaisePower(inNumber, inPower - 1);
+}
+
+//=============================================================================
+/**
+ * Parse the string into an __int64.
+ *
+ * @param inString the string to parse.
+ * @param inStringLen the length of the string.
+ * @param inBase the base of the character encoding (16 is Hex, 10 is decimal).
+ *
+ * @return <the parsed string.
+ */
+//=============================================================================
+unsigned __int64 CWinUtils::StringToInt64(const char *inString, unsigned short inStringLen,
+ unsigned short inBase)
+{
+ unsigned __int64 theKey = 0;
+ char theChar;
+ unsigned short i;
+
+ for (i = 0; i < inStringLen; ++i) {
+ theChar = inString[i];
+ if (theChar < 'A')
+ theChar -= '0';
+ else if (theChar < 'a')
+ theChar -= 'A' - 10;
+ else
+ theChar -= 'a' - 10;
+
+ theKey +=
+ ((unsigned __int64)theChar) * (unsigned __int64)RaisePower(inBase, inStringLen - 1 - i);
+ }
+ return theKey;
+}
+
+//=============================================================================
+/**
+ * Get a wchar_t from an MFC CString (used to go to Q3DStudio::CString without flattening unicode)
+ *
+ * @param inMFCString the string convert
+ *
+ * @return <the null-terminated wchar_t buffer. caller must delete[]!!!!
+ */
+//=============================================================================
+wchar_t *CWinUtils::WideFromMFC(::CString inMFCString)
+{
+ TCHAR *theBuffer = inMFCString.GetBuffer(0);
+ long theMultiLength = inMFCString.GetLength();
+ wchar_t *theDestBuffer = new wchar_t[theMultiLength * 2 + 1]; // times 2 so we know we are big
+ // enough for 1 and 2 byte chars
+ // from multibyte
+ wcscpy(theDestBuffer, theBuffer);
+ inMFCString.ReleaseBuffer();
+ return theDestBuffer;
+} \ No newline at end of file
diff --git a/src/Authoring/Studio/_Win/Utils/WinUtils.h b/src/Authoring/Studio/_Win/Utils/WinUtils.h
new file mode 100644
index 00000000..121a61bd
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Utils/WinUtils.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef INCLUDED_WIN_UTILS_H
+#define INCLUDED_WIN_UTILS_H 1
+
+#pragma once
+
+class CWinUtils
+{
+public:
+ static BOOL AlphaBlendExt(HDC hDCDest, short x, short y, short cx, short cy, HDC hDCSrc,
+ short sx, short sy, short sw, short sh, short inAlpha);
+ static void DrawAlphaBlendBitmap(CDC *inDC, short inDestX, short inDestY, HBITMAP inBmp,
+ short inWidth, short inHeight, short inSourceX,
+ short inSourceY, short inAlpha, BOOL inTransparentFlag = FALSE,
+ COLORREF inColorTransparent = RGB(0x00, 0x00, 0x00));
+ static void DrawBitmap(CDC *inDC, CPoint inPos, HBITMAP inBitmap);
+ static void DrawTransparentBitmap(CDC *pDC, long x, long y, HBITMAP hBmp,
+ COLORREF colorTransparent, long w = -1, long h = -1,
+ long sx = 0, long sy = 0);
+ static BOOL TransparentBltExt(HDC inDCDest, long inXOriginDest, long inYOriginDest,
+ long inWidthDest, long inHeightDest, HDC inDCSrc,
+ long inXOriginSrc, long inYOriginSrc, long inWidthSrc,
+ long inHeightSrc, UINT inColorTransparent);
+
+ static void GetStudioLogFont(LOGFONT &outLogFont);
+ static unsigned __int64 StringToInt64(const char *inString, unsigned short inStringLen,
+ unsigned short inBase);
+ static void CopyFileToArchive(CString inFilename, CArchive &inDestination);
+ static void CopyArchiveToFile(CArchive &inArchive, CString inDestination,
+ unsigned long inLength);
+ static wchar_t *WideFromMFC(::CString inMFCString);
+
+protected:
+ static unsigned __int64 RaisePower(unsigned __int64 inNumber, unsigned long inPower);
+};
+
+#endif // INCLUDED_WIN_UTILS_H
diff --git a/src/Authoring/Studio/_Win/Workspace/Dialogs.cpp b/src/Authoring/Studio/_Win/Workspace/Dialogs.cpp
new file mode 100644
index 00000000..517aed97
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Workspace/Dialogs.cpp
@@ -0,0 +1,1332 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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 "stdafx.h"
+#include "qtAuthoring-config.h"
+#include "Strings.h"
+#include "StringLoader.h"
+
+#include "Dialogs.h"
+#include "StudioApp.h"
+#include "Doc.h"
+
+#include "InterpolationDlg.h"
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "UICMessageBox.h"
+#include "StringTokenizer.h"
+#include "Resource.h"
+#include "Preferences.h"
+#include "ProgressPalette.h"
+#include "ProgressView.h"
+#include "Views.h"
+#include "WinUtils.h"
+#include "MasterP.h"
+#include "TimeEditDlg.h"
+#include "StudioPreferences.h"
+#include "ResetKeyframeValuesDlg.h"
+#include "GLVersionDlg.h"
+#endif
+#include "Core.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "UICMacros.h"
+#include "IDocumentEditor.h"
+#include "UICFileTools.h"
+#endif
+#include "ImportUtils.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "FileDialogEx.h"
+#endif
+
+#include "StringLoader.h"
+
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QStandardPaths>
+
+#include <iostream>
+
+//=============================================================================
+/**
+ * Constructor
+ * @param inShowGUI true if dialogs should be displayed or piped to std:cout instead
+ */
+CDialogs::CDialogs(bool inShowGUI /*= true*/)
+#ifdef KDAB_TEMPORARILY_REMOVED
+ : m_ProgressPalette(nullptr)
+ , m_ShowGUI(inShowGUI)
+ , m_LastSaveFile(CUICFile::GetApplicationDirectory().GetAbsolutePath())
+#endif
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CDialogs::~CDialogs()
+{
+}
+
+//=============================================================================
+/**
+ * Displays a multiline text edit.
+ * @param ioText
+ * @param inNotification
+ */
+#if 0
+void CDialogs::DisplayMultilineTextEdit(Q3DStudio::CString &ioText,
+ CMultilineEditDlg::INotification *inNotifiction)
+{
+ CRct theLocation = CStudioPreferences::GetMultilineTextLocation();
+
+ CMultilineEditDlg theMultilineEditDlg(inNotifiction, theLocation);
+ theMultilineEditDlg.SetString(ioText);
+ if (theMultilineEditDlg.DoModal() == IDOK) {
+ // Set the string
+ ioText = theMultilineEditDlg.GetString();
+
+ // Save the window position
+ theLocation = theMultilineEditDlg.GetLocation();
+ CStudioPreferences::SetMultilineTextLocation(theLocation);
+ }
+}
+#endif
+
+//=============================================================================
+/**
+ * Displays a dialog asking the user to choose the keyframe interpolation.
+ *
+ * @param ioEaseIn value to be set as the ease in default - passes back the value chosen by the user
+ * @param ioEaseOut value to be set as the ease out default - passes back the value chosen by the
+ * user
+ * @return true if the user clicked OK on the dialog (indicating that the values should be updated
+ * on the track)
+ */
+bool CDialogs::PromptForKeyframeInterpolation(float &ioEaseIn, float &ioEaseOut)
+{
+ bool theReturnValue = false;
+
+ CInterpolationDlg theInterpolationDialog;
+ theInterpolationDialog.setEaseIn(ioEaseIn);
+ theInterpolationDialog.setEaseOut(ioEaseOut);
+
+ // If the user presses the OK button
+ if (theInterpolationDialog.exec() == QDialog::Accepted) {
+ // Retrieve the new interpolation values
+ ioEaseIn = theInterpolationDialog.easeIn();
+ ioEaseOut = theInterpolationDialog.easeOut();
+ theReturnValue = true;
+ }
+
+ return theReturnValue;
+}
+
+//=============================================================================
+/**
+ * Notify the user that the deletion of an asset has failed.
+ */
+void CDialogs::DisplayAssetDeleteFailed()
+{
+ Q3DStudio::CString theMessage =
+ ::LoadResourceString(IDS_ERROR_CLIENTSAVE); // TODO: Should display the correct string
+ Q3DStudio::CString theTitle = ::LoadResourceString(IDS_ERROR_MSGTITLE);
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theMessage, CUICMessageBox::ICON_ERROR, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << theMessage.GetCharStar() << std::endl;
+ }
+}
+
+//=============================================================================
+/**
+ * Get the export choice.
+ */
+CUICFile CDialogs::GetExportChoice(const Q3DStudio::CString &, const Q3DStudio::CString &)
+{
+ // Need to fix this for windows if we decide to use it
+ return CUICFile("", false, false);
+}
+
+//==============================================================================
+/**
+ * Notify that we are unable to refresh the resource.
+ */
+void CDialogs::DisplayRefreshResourceFailed(const Q3DStudio::CString &inResourceName,
+ const Q3DStudio::CString &inDescription)
+{
+ Q3DStudio::CString theTitle(::LoadResourceString(IDS_ERROR_REFRESHRESOURCETITLE));
+
+ Q3DStudio::CString theText;
+ theText.Format(::LoadResourceString(IDS_ERROR_REFRESHRESOURCETEXT),
+ static_cast<const wchar_t *>(inResourceName));
+
+ if (!inDescription.IsEmpty())
+ theText += inDescription;
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theText, CUICMessageBox::ICON_WARNING, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << theText.GetCharStar() << std::endl << std::endl;
+ }
+}
+
+//=============================================================================
+/**
+ * Notify the user that the loading of the requested resource failed.
+ *
+ * Possible failed import messages are:
+ * IDS_ERROR_IMPORTLUARESOURCETEXT - Sorry - Studio was unable to
+ *import the LUA script.\nPlease check the file and try again.\nNote that LUA files must be
+ *syntactically correct to be importable.
+ * IDS_ERROR_IMPORTRESOURCETEXT - Sorry - Studio was unable to
+ *import the resource.\nPlease check the above file and try again.
+ * IDS_ERROR_IMPORTUNSUPPORTEDRESOURCETYPETEXT - Sorry - Studio was unable to import
+ *the resource file.\nThis resource file type is not currently supported by Studio.\n
+ *
+ * @param inURL the URL for the asset that was to have been imported
+ * @param inErrorDescription description for the failure, if any
+ * @param inWarningsOnly not a failure, just warnings
+ */
+void CDialogs::DisplayImportFailed(const QUrl &inURL, const QString &inDescription,
+ bool inWarningsOnly)
+{
+ // Notify the user we couldn't load the resource.
+ Q3DStudio::CString theTitle, theText, theMsgText;
+
+ theTitle = ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETITLE);
+ // specify if its an error or warning
+ theTitle = (!inWarningsOnly) ? ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETITLE_ERROR)
+ : ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETITLE_WARNING);
+
+ // Determine the asset type
+ EStudioObjectType theAssetType =
+ Q3DStudio::ImportUtils::GetObjectFileTypeForFile(inURL.path(), false)
+ .m_ObjectType;
+
+ bool theIsStudioObject = theAssetType != OBJTYPE_UNKNOWN;
+
+ // Is this a LUA file, but perhaps incorrectly formatted?
+ if (theAssetType == OBJTYPE_BEHAVIOR) {
+ // Load the message about the LUA format
+ if (inWarningsOnly)
+ theText = ::LoadResourceString(IDS_WARNING_IMPORTLUARESOURCETEXT);
+ else
+ theText = ::LoadResourceString(IDS_ERROR_IMPORTLUARESOURCETEXT);
+ if (!inDescription.isEmpty()) {
+ theText += L"\n";
+ theText += Q3DStudio::CString::fromQString(inDescription);
+ }
+ } else if (theAssetType != OBJTYPE_UNKNOWN || theIsStudioObject) {
+ // Valid registered file type, but invalid file
+
+ bool theNoDescription = inDescription.isEmpty();
+ // Load default text stating that the import resource failed.
+ // descriptions if present are presented as "reasons" for failure.
+ if (!inWarningsOnly || theNoDescription) {
+ theText.Format(::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT), theNoDescription
+ ? L"."
+ : ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_REASON).c_str());
+ theText += "\n";
+ }
+ if (!theNoDescription)
+ theText += Q3DStudio::CString::fromQString(inDescription);
+ else
+ theText += ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_CHECKFILE);
+ } else {
+ // Display the warning messsage if we have one
+ // instead of a meaningless message. This provides more feed back
+ if (!inDescription.isEmpty())
+ theText += Q3DStudio::CString::fromQString(inDescription);
+ else
+ theText = ::LoadResourceString(
+ IDS_ERROR_IMPORTUNSUPPORTEDRESOURCETYPETEXT); // Load default text stating that the
+ // import resource failed.
+ }
+
+ Q3DStudio::CString theFormatString(
+ !inWarningsOnly ? ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_FAILED)
+ : ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_COMPLETEWITHWARNING));
+ theFormatString += _UIC("\n%ls\n\n");
+ std::wstring wstr = inURL.path().toStdWString();
+ theMsgText.Format(theFormatString, static_cast<const wchar_t *>(wstr.c_str()));
+ theMsgText += theText;
+
+ // Display the failed import resource message.
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theMsgText, CUICMessageBox::ICON_WARNING, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << theMsgText.GetCharStar() << std::endl;
+ }
+}
+
+namespace {
+
+inline Q3DStudio::CString CreateExtensionsList(const char **extList)
+{
+ Q3DStudio::CString retval;
+ for (const char **ext = extList; *ext != nullptr; ++ext) {
+ if (retval.Length())
+ retval += " ";
+ retval += Q3DStudio::CString("*.") + *ext;
+ }
+ return retval;
+}
+
+struct SAllowedTypesEntry
+{
+ Q3DStudio::DocumentEditorFileType::Enum m_FileType;
+ long m_ResourceStringId; // Model Files, Image Files, etc
+ const char **m_FileExtensions;
+};
+const char *imgExts[] = {
+ "png", "jpg", "jpeg", "dds", "bmp", "gif", "hdr", nullptr,
+};
+const wchar_t *wideImgExts[] = {
+ L"png", L"jpg", L"jpeg", L"dds", L"bmp", L"gif", L"hdr", nullptr,
+};
+const char *modelExts[] = {
+ CDialogs::GetDAEFileExtension(),
+#ifdef QT_3DSTUDIO_FBX
+ CDialogs::GetFbxFileExtension(),
+#endif
+ // TODO CDialogs::GetImportFileExtension(),
+ // TODO CDialogs::GetMeshFileExtension(),
+ nullptr,
+};
+const char *meshExts[] = {
+ CDialogs::GetMeshFileExtension(), nullptr,
+};
+const char *importExts[] = {
+ CDialogs::GetImportFileExtension(), nullptr,
+};
+const char *behaviorExts[] = {
+ CDialogs::GetLUAFileExtension(), nullptr,
+};
+const char *fontExts[] = {
+ "ttf", "otf", nullptr,
+};
+const wchar_t *wideFontExts[] = {
+ L"ttf", L"otf", nullptr,
+};
+const char *effectExts[] = {
+ "effect", nullptr,
+};
+const wchar_t *wideEffectExts[] = {
+ L"effect", nullptr,
+};
+const char *materialExts[] = {
+ "material", nullptr,
+};
+const wchar_t *wideMaterialExts[] = {
+ L"material", nullptr,
+};
+const char *soundExts[] = {
+ "wav", nullptr,
+};
+const wchar_t *wideSoundExts[] = {
+ L"wav", nullptr,
+};
+
+// List of file types allowed during import
+SAllowedTypesEntry g_AllowedImportTypes[] = {
+ { Q3DStudio::DocumentEditorFileType::DAE, IDS_LIBRARYIMPORT_MODEL, modelExts },
+#ifdef QT_3DSTUDIO_FBX
+ { Q3DStudio::DocumentEditorFileType::FBX, IDS_LIBRARYIMPORT_MODEL, modelExts },
+#endif
+};
+size_t g_NumAllowedImportTypes = sizeof(g_AllowedImportTypes) / sizeof(*g_AllowedImportTypes);
+
+// List of file types allowed for file references
+SAllowedTypesEntry g_AllowedFileReferencesTypes[] = {
+ { Q3DStudio::DocumentEditorFileType::Image, IDS_LIBRARYIMPORT_IMAGE, imgExts },
+ { Q3DStudio::DocumentEditorFileType::Behavior, IDS_LIBRARYIMPORT_BEHAVIOR, behaviorExts },
+ { Q3DStudio::DocumentEditorFileType::Mesh, IDS_LIBRARYIMPORT_MESH, meshExts },
+ { Q3DStudio::DocumentEditorFileType::Import, IDS_LIBRARYIMPORT_IMPORT, importExts },
+ { Q3DStudio::DocumentEditorFileType::Effect, IDS_LIBRARYIMPORT_EFFECT, effectExts },
+};
+size_t g_NumAllowedFileReferencesTypes =
+ sizeof(g_AllowedFileReferencesTypes) / sizeof(*g_AllowedFileReferencesTypes);
+}
+
+QString CDialogs::ConfirmRefreshModelFile(const QString &inFile)
+{
+ // this produces an extension string which contains all allowed formats specified in
+ // g_AllowedImportTypes
+ // currently DAE and FBX
+ QString theFileFilter =
+ CreateAllowedTypesString(Q3DStudio::DocumentEditorFileType::DAE, true);
+
+
+ return QFileDialog::getOpenFileName(qApp->activeWindow(), QObject::tr("Open"),
+ inFile, theFileFilter);
+}
+
+//==============================================================================
+/**
+ * Allows the user to select/confirm the file to fix broken file reference.
+ * This method opens a file dialog to the specified location, and allows the user to
+ * accept, or select a different file.
+ * @param outFile The output path
+ * @param inFileType The file type filter for the dialog.
+ * @return true If the user accepted the file, false if the user canceled.
+ */
+bool CDialogs::LocateFileReference(CUICFile &outFile, long inFileType)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ Q3DStudio::CString theFileFilter = CreateAllowedTypesString(inFileType, false);
+
+ bool theResult = false;
+
+ // Open the dialog.
+ CFileDialogEx theFileDialog(TRUE, nullptr, nullptr, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
+ theFileFilter, nullptr);
+
+ // Set the initial directory to document path's directory (it should exist).
+ CUICFile theDocumentFile(g_StudioApp.GetCore()->GetDoc()->GetDocumentPath());
+ Q3DStudio::CFilePath theInitDir =
+ Q3DStudio::CFilePath(theDocumentFile.GetAbsolutePath()).GetDirectory();
+ theFileDialog.SetInitialDirectory(theInitDir);
+
+ // Set the title of the dialog
+ theFileDialog.SetWindowTitle(::LoadResourceString(IDS_PROJECT_CM_LOCATE_FILE));
+
+ INT_PTR refreshResult = theFileDialog.DoModal();
+
+ if (refreshResult == IDOK) {
+ Q3DStudio::CString thePath = theFileDialog.GetPathName();
+ Q3DStudio::CString theName = theFileDialog.GetFileName();
+ outFile = CUICFile(thePath, theName);
+
+ // The user has accepted this file.
+ theResult = true;
+ }
+
+ return theResult;
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * Allows the user to select/confirm the folder to fix broken folder reference.
+ * This method opens a folder dialog to the specified location, and allows the user to
+ * accept, or select a different folder.
+ * @param outFile The output path
+ * @return true If the user accepted the file, false if the user canceled.
+ */
+bool CDialogs::LocateFolderReference(CUICFile &outFile)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // Set the initial directory to document path's directory (it should exist).
+ CUICFile theDocumentFile(g_StudioApp.GetCore()->GetDoc()->GetDocumentPath());
+ Q3DStudio::CFilePath theInitDir =
+ Q3DStudio::CFilePath(theDocumentFile.GetAbsolutePath()).GetDirectory();
+
+ // Set the title of the dialog
+ Q3DStudio::CString theDialogTitle(::LoadResourceString(IDS_PROJECT_CM_LOCATE_FOLDER));
+
+ return BrowseForFolderDialog(outFile, theInitDir, theDialogTitle);
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * BrowseCallbackProc: Handles the callback proc for SHBrowseForFolder()
+ *
+ * Handles selecting the correct path when the SHBrowseForFolder dialog is
+ * initially displayed.
+ */
+#ifdef KDAB_TEMPORARILY_REMOVED
+static int CALLBACK BrowseCallbackProc(HWND inHwnd, UINT inMsg, LPARAM /*inlParam*/,
+ LPARAM inlpData)
+{
+ switch (inMsg) {
+ case BFFM_INITIALIZED:
+ // Indicates the browse dialog box has finished initializing. The lParam value is zero.
+ if (inlpData != nullptr) {
+ // Do so by sendint the BFFM_SETSELECTION message to the inHwnd:
+ // Selects the specified folder. To use a PIDL to specify the folder, set the
+ // message's lParam to the PIDL, and set wParam to FALSE. To specify the folder's
+ // path, set the message's lParam value to point to a nullptr-terminated string with
+ // the path, and set wParam to TRUE.
+
+ SendMessage(inHwnd, BFFM_SETSELECTION, (WPARAM)TRUE, (LPARAM)inlpData);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+#endif
+
+//==============================================================================
+/**
+ * Show browse for folder dialog
+ * @param outFile The output path
+ * @param inDefaultDir The default directory
+ * @param inDialogTitle The title of the dialog
+ * @return true If the user accepted the file, false if the user canceled.
+ */
+bool CDialogs::BrowseForFolderDialog(CUICFile &outFile, Q3DStudio::CString inDefaultDir,
+ Q3DStudio::CString inDialogTitle)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ bool theResult = false;
+ BROWSEINFO theInfo = { 0 };
+ TCHAR theDispName[MAX_PATH] = { '\0' };
+
+ theInfo.pszDisplayName = theDispName;
+ theInfo.lpszTitle = inDialogTitle;
+ theInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS | BIF_NONEWFOLDERBUTTON;
+ theInfo.lpfn = BrowseCallbackProc;
+ theInfo.lParam = (LPARAM)inDefaultDir.c_str();
+
+ // Ask the user to choose a directory
+ LPITEMIDLIST theItem = SHBrowseForFolder(&theInfo);
+
+ if (theItem != nullptr) {
+ TCHAR thePath[MAX_PATH] = { '\0' };
+ // If a path was chosen
+ if (::SHGetPathFromIDList(theItem, thePath)) {
+ theResult = true;
+ outFile = CUICFile(Q3DStudio::CString(thePath));
+ }
+
+ // Free Memory used
+ LPMALLOC thePMalloc = 0;
+ if (SUCCEEDED(SHGetMalloc(&thePMalloc))) {
+ thePMalloc->Free(theItem);
+ thePMalloc->Release();
+ }
+ }
+
+ return theResult;
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * Notify the user that the presentation we tried to load has failed.
+ * @param inPresentation The AKFile that we failed to load.
+ */
+void CDialogs::DisplayLoadingPresentationFailed(const CUICFile &inPresentation,
+ long inErrorIDS /*= -1 */)
+{
+ Q_UNUSED(inPresentation);
+
+ if (inErrorIDS == -1) // if unspecified, default to the 'generic' string
+ inErrorIDS = IDS_ERROR_LOADPRESENTATION;
+ Q3DStudio::CString theErrorMessage;
+ theErrorMessage.Format(::LoadResourceString(inErrorIDS),
+ static_cast<const wchar_t *>(inPresentation.GetName()));
+ Q3DStudio::CString theErrorTitle(::LoadResourceString(IDS_ERROR_LOADPRESENTATION_TITLE));
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theErrorTitle, theErrorMessage, CUICMessageBox::ICON_WARNING, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theErrorTitle.GetCharStar() << ": " << theErrorMessage.GetCharStar() << std::endl;
+ }
+}
+
+//==============================================================================
+/**
+ * Notify the user that the presentation we tried to save has failed.
+ *
+ * @param inSavedLocation The AKFile that we failed to save.
+ */
+void CDialogs::DisplaySavingPresentationFailed()
+{
+ Q3DStudio::CString theErrorMessage = ::LoadResourceString(IDS_ERROR_EXPORTPRESENTATION);
+ Q3DStudio::CString theErrorTitle = ::LoadResourceString(IDS_PROJNAME);
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theErrorTitle, theErrorMessage, CUICMessageBox::ICON_WARNING, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theErrorTitle.GetCharStar() << ": " << theErrorMessage.GetCharStar() << std::endl;
+ }
+}
+
+//==============================================================================
+/**
+ * Display a message box to indicate failure to overwrite a read-only file
+ *
+ * @param inSavedLocation
+ * the file location to be saved
+ *
+ * @return void
+ */
+void CDialogs::DisplaySaveReadOnlyFailed(const CUICFile &inSavedLocation)
+{
+ Q3DStudio::CString theMsg = ::LoadResourceString(IDS_SAVE_READONLY_WARNING);
+ Q3DStudio::CString theTitle = ::LoadResourceString(IDS_PROJNAME);
+
+ Q3DStudio::CString theFormattedText;
+ theFormattedText.Format(theMsg, static_cast<const wchar_t *>(inSavedLocation.GetName()));
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theFormattedText, CUICMessageBox::ICON_WARNING, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << theFormattedText.GetCharStar() << std::endl;
+ }
+}
+
+//==============================================================================
+/**
+ * Displays a CUICMessageBox using the specified parameters. The message box
+ * is modal to the main frame. This provides an easy way to place modal dialogs
+ * to the user, without requiring your class to know about the main frame or
+ * window refs.
+ * @param inTitle Title of the message box (not used on Mac)
+ * @param inText Text of the message
+ * @param inIcon Icon to be displayed next to the text
+ * @param inShowCancel true to show a Cancel button, false only show an OK button
+ * @return Indication of which button was pressed to dismiss the dialog
+ */
+CUICMessageBox::EMessageBoxReturn
+CDialogs::DisplayMessageBox(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inText,
+ CUICMessageBox::EMessageBoxIcon inIcon, bool inShowCancel)
+{
+ CUICMessageBox::EMessageBoxReturn theUserChoice;
+
+ if (m_ShowGUI) {
+ theUserChoice =
+ CUICMessageBox::Show(inTitle, inText, inIcon, inShowCancel, qApp->activeWindow());
+ } else {
+ std::cout << inTitle.GetCharStar() << ": " << inText.GetCharStar() << std::endl;
+ theUserChoice = CUICMessageBox::MSGBX_OK;
+ }
+
+ return theUserChoice;
+}
+
+int CDialogs::DisplayChoiceBox(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inText,
+ int inIcon)
+{
+ if (m_ShowGUI) {
+ QMessageBox box;
+ box.setWindowTitle(inTitle.toQString());
+ box.setText(inText.toQString());
+ switch (inIcon) {
+ case CUICMessageBox::ICON_WARNING:
+ box.setIcon(QMessageBox::Warning);
+ break;
+ case CUICMessageBox::ICON_ERROR:
+ box.setIcon(QMessageBox::Critical);
+ break;
+ case CUICMessageBox::ICON_INFO:
+ box.setIcon(QMessageBox::Information);
+ break;
+ default:
+ break;
+ }
+ box.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+ switch (box.exec()) {
+ case QMessageBox::Yes:
+ return IDYES;
+ case QMessageBox::No:
+ return IDNO;
+ default:
+ Q_UNREACHABLE();
+ }
+ } else {
+ std::cout << inTitle.GetCharStar() << ": " << inText << std::endl;
+ return IDYES;
+ }
+}
+
+const char *CDialogs::GetDAEFileExtension()
+{
+ return "dae";
+}
+const char *CDialogs::GetFbxFileExtension()
+{
+ return "fbx";
+}
+// Null terminated list
+const char **CDialogs::GetImgFileExtensions()
+{
+ return imgExts;
+}
+const char *CDialogs::GetImportFileExtension()
+{
+ return "import";
+}
+const char *CDialogs::GetMeshFileExtension()
+{
+ return "mesh";
+}
+const char *CDialogs::GetLUAFileExtension()
+{
+ return "lua";
+}
+const char *CDialogs::GetQmlFileExtension()
+{
+ return "qml";
+}
+const char **CDialogs::GetFontFileExtensions()
+{
+ return fontExts;
+}
+const char **CDialogs::GetEffectFileExtensions()
+{
+ return effectExts;
+}
+const char **CDialogs::GetMaterialFileExtensions()
+{
+ return materialExts;
+}
+const char **CDialogs::GetSoundFileExtensions()
+{
+ return soundExts;
+}
+
+bool IsFileExtension(const char *inExt, const char **inExts)
+{
+ if (inExt == nullptr)
+ return false;
+ for (const char **ext = inExts; *ext != nullptr; ++ext)
+ if (QString::compare(inExt, *ext, Qt::CaseInsensitive) == 0)
+ return true;
+ return false;
+}
+bool CDialogs::IsImageFileExtension(const char *inExt)
+{
+ return IsFileExtension(inExt, imgExts);
+}
+bool CDialogs::IsFontFileExtension(const char *inExt)
+{
+ return IsFileExtension(inExt, fontExts);
+}
+bool CDialogs::IsEffectFileExtension(const char *inExt)
+{
+ return IsFileExtension(inExt, effectExts);
+}
+bool CDialogs::IsMaterialFileExtension(const char *inExt)
+{
+ return IsFileExtension(inExt, materialExts);
+}
+bool CDialogs::IsSoundFileExtension(const char *inExt)
+{
+ return IsFileExtension(inExt, soundExts);
+}
+
+const wchar_t **CDialogs::GetWideImgFileExtensions()
+{
+ return wideImgExts;
+}
+const wchar_t *CDialogs::GetWideDAEFileExtension()
+{
+ return L"dae";
+}
+const wchar_t *CDialogs::GetWideFbxFileExtension()
+{
+ return L"fbx";
+}
+const wchar_t *CDialogs::GetWideImportFileExtension()
+{
+ return L"import";
+}
+const wchar_t *CDialogs::GetWideMeshFileExtension()
+{
+ return L"mesh";
+}
+const wchar_t *CDialogs::GetWideLUAFileExtension()
+{
+ return L"lua";
+}
+const wchar_t **CDialogs::GetWideFontFileExtensions()
+{
+ return wideFontExts;
+}
+const wchar_t **CDialogs::GetWideEffectFileExtensions()
+{
+ return wideEffectExts;
+}
+const wchar_t **CDialogs::GetWideMaterialFileExtensions()
+{
+ return wideMaterialExts;
+}
+
+bool IsFileExtension(const wchar_t *inExt, const wchar_t **inExts)
+{
+ if (inExt == nullptr)
+ return false;
+ for (const wchar_t **ext = inExts; *ext != nullptr; ++ext) {
+ if (QString::compare(QString::fromWCharArray(inExt),
+ QString::fromWCharArray(*ext), Qt::CaseInsensitive) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+bool CDialogs::IsImageFileExtension(const wchar_t *inExt)
+{
+ return IsFileExtension(inExt, wideImgExts);
+}
+bool CDialogs::IsFontFileExtension(const wchar_t *inExt)
+{
+ return IsFileExtension(inExt, wideFontExts);
+}
+bool CDialogs::IsEffectFileExtension(const wchar_t *inExt)
+{
+ return IsFileExtension(inExt, wideEffectExts);
+}
+
+bool CDialogs::IsMaterialFileExtension(const wchar_t *inExt)
+{
+ return IsFileExtension(inExt, wideMaterialExts);
+}
+
+bool CDialogs::IsPathFileExtension(const wchar_t *inExt)
+{
+ return QString::compare(QString::fromWCharArray(inExt), "svg", Qt::CaseInsensitive) == 0;
+}
+
+bool CDialogs::IsPathBufferExtension(const wchar_t *inExt)
+{
+ return QString::compare(QString::fromWCharArray(inExt), "path", Qt::CaseInsensitive) == 0;
+}
+
+bool CDialogs::IsSoundFileExtension(const wchar_t *inExt)
+{
+ return IsFileExtension(inExt, wideSoundExts);
+}
+
+//==============================================================================
+/**
+ * File picker.
+ * Format for filter is as follows:
+ * Each entry in the filter list is '<description>|*.ext'
+ * String must end with '|'
+ * Example, XML Exporter (*.xml)|*.xml|All files (*.*)|*.*|
+ *
+ * @param inFileExtensionFilter Well-formed extension filter string. See comments
+ *above for the format.
+ * @param inDefault Default string in case of abortion or
+ *failure
+ * @return chosen file path if successful, inDefault otherwise.
+ */
+Q3DStudio::CString CDialogs::GetFilePathChoice(const Q3DStudio::CString &inFileExtensionFilter,
+ const Q3DStudio::CString &inDefault,
+ const Q3DStudio::CString *inDialogTitle /*= nullptr */)
+{
+ Q3DStudio::CString theResult(inDefault);
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CFileDialogEx theFileDlg(true, nullptr, nullptr, 0, inFileExtensionFilter, AfxGetMainWnd());
+
+ Q3DStudio::CString theInitDir =
+ CPreferences::GetUserPreferences().GetStringValue("LastChosenFile", "");
+ theFileDlg.SetInitialDirectory(theInitDir);
+
+ // Remember the filter setting between invokations
+ static long s_LastFilterIndex = -1;
+ if (s_LastFilterIndex > 0)
+ theFileDlg.SetFilterIndex(s_LastFilterIndex);
+
+ if (inDialogTitle) // Set the title of the dialog if specied
+ theFileDlg.SetWindowTitle(*inDialogTitle);
+
+ if (theFileDlg.DoModal() == IDOK) {
+ theResult = theFileDlg.GetPathName();
+ CPreferences::GetUserPreferences().SetStringValue("LastChosenFile", theResult);
+ s_LastFilterIndex = theFileDlg.GetLastFilterIndex();
+ }
+#endif
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * CreateAllowedTypesString: Creates the string used to determine allowable types for import or
+ *for filereferences
+ * @return the string that dynamicly created with the extensions supported.
+ */
+QString CDialogs::CreateAllowedTypesString(long inFileTypeFilter, bool inForImport)
+{
+ QString theReturnString;
+ size_t theCount = inForImport ? g_NumAllowedImportTypes : g_NumAllowedFileReferencesTypes;
+ for (size_t idx = 0; idx < theCount; ++idx) {
+ const SAllowedTypesEntry &entry =
+ inForImport ? g_AllowedImportTypes[idx] : g_AllowedFileReferencesTypes[idx];
+ if (inFileTypeFilter == Q3DStudio::DocumentEditorFileType::Unknown
+ || inFileTypeFilter == entry.m_FileType) {
+ QString theTypeString(::LoadResourceString(entry.m_ResourceStringId).toQString());
+ QString theExtensions(CreateExtensionsList(entry.m_FileExtensions).toQString());
+ theReturnString += theTypeString + " (" + theExtensions + ");;";
+ }
+ }
+ return theReturnString;
+}
+
+//==============================================================================
+/**
+ * Display a error dialog box with the given text string that describes the error.
+ */
+void CDialogs::DisplayKnownErrorDialog(const Q3DStudio::CString &inErrorText)
+{
+ if (inErrorText.Length() > 0) // make sure this is valid
+ {
+ Q3DStudio::CString theTitle(::LoadResourceString(IDS_PROJNAME));
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, inErrorText, CUICMessageBox::ICON_ERROR, false,
+ qApp->activeWindow());
+ else
+ std::cout << inErrorText.GetCharStar() << ": " << inErrorText.GetCharStar() << std::endl;
+ }
+}
+
+//==============================================================================
+/**
+ * Prompt the user to save the document before losing their changes.
+ * This is used when closing, loading or newing up a document when the current
+ * one has modifications.
+ * @return the user's choice.
+ */
+CDialogs::ESavePromptResult CDialogs::PromptForSave()
+{
+ Q3DStudio::CString theDocTitle;
+
+ CUICFile theCurrentDoc = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath();
+ if (theCurrentDoc.IsFile())
+ theDocTitle = theCurrentDoc.GetName();
+ else // if the current doc has not been saved then use the default title.
+ theDocTitle = ::LoadResourceString(IDS_UNTITLED_DOCUMENT_TITLE);
+
+ Q3DStudio::CString thePrompt = ::LoadResourceString(IDS_PROMPT_FOR_SAVE);
+ thePrompt.Format(thePrompt, static_cast<const wchar_t *>(theDocTitle));
+
+ int theChoice = QMessageBox::warning(nullptr, ::LoadResourceString(IDS_PROJNAME).toQString(),
+ thePrompt.toQString(), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
+
+ ESavePromptResult theResult = CANCEL_OPERATION;
+
+ switch (theChoice) {
+ case QMessageBox::Yes:
+ theResult = SAVE_FIRST;
+ break;
+ case QMessageBox::No:
+ theResult = CONTINUE_NO_SAVE;
+ break;
+ case QMessageBox::Cancel:
+ theResult = CANCEL_OPERATION;
+ break;
+ default:
+ break;
+ }
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Prompt the user for a file to save to from the SaveAs menu option.
+ * @return an invalid file if the user cancels the save dialog.
+ */
+std::pair<CUICFile, bool> CDialogs::GetSaveAsChoice(const Q3DStudio::CString &inDialogTitle,
+ bool inFilenameUntitled)
+{
+ CUICFile theFile("");
+ Q3DStudio::CString theFileExt;
+ Q3DStudio::CString theImportFilter;
+
+ Q3DStudio::CString theFilename = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath().GetAbsolutePath();
+
+ if (theFilename == "" || inFilenameUntitled)
+ theFilename = ::LoadResourceString(IDS_UNTITLED_DOCUMENT_TITLE);
+
+ theFileExt = ::LoadResourceString(IDS_FILE_EXT_UIP);
+ theImportFilter = ::LoadResourceString(IDS_FILE_DESC_UIP);
+
+ theImportFilter += " (*" + theFileExt + ")|*" + theFileExt + "|";
+
+ QFileDialog theFileDlg;
+ theFileDlg.setOption(QFileDialog::DontConfirmOverwrite);
+ const QFileInfo fi(m_LastSaveFile.toQString());
+ theFileDlg.setDirectory((fi.path() == QLatin1Char('.')) ? QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) : fi.path());
+ theFileDlg.setAcceptMode(QFileDialog::AcceptSave);
+ theFileDlg.setDefaultSuffix(theFileExt.toQString());
+ if (inDialogTitle != "")
+ theFileDlg.setWindowTitle(inDialogTitle.toQString());
+
+ bool theCreateDir = false;
+ bool theShowDialog = true;
+
+ while (theShowDialog && theFileDlg.exec()) {
+ theShowDialog = false;
+ theFile = CUICFile(Q3DStudio::CString::fromQString(theFileDlg.selectedFiles().front()));
+
+ m_LastSaveFile = theFile.GetAbsolutePath();
+ // customising a dialog box will force us to use non-native.
+ // defaulting this for now, until we can agree a better workflow for
+ // creating new projects
+ theCreateDir = true;
+
+ if (theCreateDir) {
+ // If user checks "Create directory for project"
+ // we need to check manually if the file in the directory already exists (because the
+ // default file dialog can't do that for you)
+ // If the file exists, show warning message if user wants to overwrite the file
+ // This is to fix bug #6315: Create new project in folder with same name will overwrite
+ // existing file without warning
+ Q3DStudio::CFilePath theFinalDir;
+ Q3DStudio::CFilePath theFinalDoc;
+ g_StudioApp.GetCore()->GetCreateDirectoryFileName(theFile, theFinalDir, theFinalDoc);
+
+ // Update last save file to final doc
+ m_LastSaveFile = theFinalDoc;
+ if (theFinalDoc.Exists()) {
+ const QString theTitle(QObject::tr("Confirm Save As"));
+ const QString filePath(theFinalDir.GetFileName().toQString() + QDir::separator() + theFinalDoc.GetFileName().toQString());
+ const QString theString = QObject::tr("%1 already exists.\nDo you want to replace it?").arg(filePath);
+
+ auto result = QMessageBox::question(nullptr, theTitle, theString);
+ if (result != QMessageBox::Yes) {
+ // Reset the file and show the file dialog again
+ theFile = CUICFile("");
+ theShowDialog = true;
+ continue;
+ }
+ } // of over-writing case
+ }
+ }
+
+ return std::make_pair(theFile, theCreateDir);
+}
+
+//==============================================================================
+/**
+ * Prompt the user for a file to create.
+ * @return an invalid file if the user cancels the save dialog.
+ */
+std::pair<CUICFile, bool>
+CDialogs::GetNewDocumentChoice(const Q3DStudio::CString &inInitialDirectory)
+{
+ if (inInitialDirectory.size())
+ m_LastSaveFile = inInitialDirectory;
+ return GetSaveAsChoice(::LoadResourceString(IDS_CREATE_NEW_DOCUMENT_TITLE), true);
+}
+
+//==============================================================================
+/**
+ * Prompt the user for a file to open.
+ * This will return an invalid file if the user cancels the save dialog.
+ */
+CUICFile CDialogs::GetFileOpenChoice(const Q3DStudio::CString &inInitialDirectory)
+{
+ CUICFile theFile("");
+ Q3DStudio::CString theFileExt;
+ Q3DStudio::CString theImportFilter;
+
+ theFileExt = ::LoadResourceString(IDS_FILE_EXT_UIP);
+ theImportFilter = ::LoadResourceString(IDS_FILE_DESC_UIP);
+
+ theImportFilter += " (*" + theFileExt + ")";
+
+ QFileDialog theFileDlg(qApp->activeWindow(), QString(), inInitialDirectory.toQString(), theImportFilter.toQString());
+ theFileDlg.setAcceptMode(QFileDialog::AcceptOpen);
+
+ if (theFileDlg.exec() == QDialog::Accepted) {
+ QFileInfo fi(theFileDlg.selectedFiles().first());
+ Q3DStudio::CString thePath = Q3DStudio::CString::fromQString(fi.absolutePath());
+ Q3DStudio::CString theName = Q3DStudio::CString::fromQString(fi.fileName());
+ theFile = CUICFile(thePath, theName);
+
+ m_LastSaveFile = theFile.GetAbsolutePath();
+ }
+
+ return theFile;
+}
+
+//==============================================================================
+/**
+ * Prompt the user to make sure they want to revert the current project.
+ * @return true if they do want to continue with the revert.
+ */
+bool CDialogs::ConfirmRevert()
+{
+ bool theConfirmation = false;
+ Q3DStudio::CString thePrompt = ::LoadResourceString(IDS_PROMPT_FOR_REVERT);
+ Q3DStudio::CString theTitle = ::LoadResourceString(IDS_PROJNAME);
+
+ CUICMessageBox::EMessageBoxReturn theChoice;
+
+ if (m_ShowGUI)
+ theChoice = CUICMessageBox::Show(theTitle, thePrompt, CUICMessageBox::ICON_WARNING, true,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << thePrompt.GetCharStar() << std::endl;
+ theChoice = CUICMessageBox::MSGBX_OK;
+ }
+
+ // user decided to go ahead and delete all unused resources
+ if (theChoice == CUICMessageBox::MSGBX_OK)
+ theConfirmation = true;
+
+ return theConfirmation;
+}
+
+//==============================================================================
+/**
+ * Displays a progress screen, if there is not one aleady being shown. The
+ * progress screen doesn't get dismissed until you call
+ * CDialogs::DestroyProgressScreen().
+ * @param inActionText text to be displayed above the file name on the screen
+ * @param inFileName name of the file that you are loading
+ * @param inWindowTitle the window's title
+ */
+void CDialogs::DisplayProgressScreen(const Q3DStudio::CString &inActionText,
+ const Q3DStudio::CString &inFileName,
+ const Q3DStudio::CString &inWindowTitle)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ if (m_ShowGUI && (!m_ProgressPalette || !m_ProgressPalette->GetSafeHwnd())) {
+ m_ProgressPalette = new CProgressPalette();
+ CViews::CreateDialogAndView(RUNTIME_CLASS(CProgressView), m_ProgressPalette,
+ (CFrameWnd *)AfxGetMainWnd(), inWindowTitle);
+ m_ProgressPalette->ShowDialog();
+ m_ProgressPalette->InitialUpdate();
+ m_ProgressPalette->SetActionText(inActionText);
+ m_ProgressPalette->SetFileName(inFileName);
+ m_ProgressPalette->RedrawWindow(nullptr, nullptr, RDW_UPDATENOW);
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Retrieve the pointer to the progress screen.
+ * @return m_ProgressPalette
+ */
+IProgressCallback *CDialogs::GetProgressScreen() const
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ return m_ProgressPalette;
+#endif
+ return nullptr;
+}
+
+//==============================================================================
+/**
+ * If a loading screen is currently being shown, this function destroys it. You
+ * can show the loading screen again with another call to
+ * CDialogs::DisplayLoadingScreen().
+ */
+void CDialogs::DestroyProgressScreen()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ if (m_ShowGUI && (m_ProgressPalette && m_ProgressPalette->GetSafeHwnd())) {
+ // Don't call delete on m_ProgressPalette. You should only call DestroyWindow on
+ // CFrameWnds. See the MSDN.
+ m_ProgressPalette->DestroyWindow();
+ m_ProgressPalette = nullptr;
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Prompt the user for the Object Timebar color.
+ * @param ioColor
+ * @return true if we successfully obtained a color using the displayed dialog.
+ */
+bool CDialogs::PromptObjectTimebarColor(CColor &ioColor)
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ std::auto_ptr<CColorDialog> theColorDlg(new CColorDialog(ioColor, CC_SOLIDCOLOR | CC_FULLOPEN));
+ ::CColor theSelectedColor;
+ if (theColorDlg->DoModal() == IDOK) {
+ ioColor = theColorDlg->GetColor();
+ return true;
+ }
+ return false;
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * Display statistics from profiling.
+ */
+void CDialogs::DisplayProfilingStatistics()
+{
+ Q3DStudio::CString theStatistics = "<Not Enabled>";
+#ifdef KDAB_TEMPORARILY_REMOVED
+#ifdef PERFORM_PROFILE
+ CMasterProf *theMasterP = CMasterProf::GetInstance();
+
+ for (long theIndex = 0; theIndex < theMasterP->GetProfilerCount(); ++theIndex) {
+ CMethProf *theProf = theMasterP->GetProfiler(theIndex);
+ if (theProf->GetCount() > 0) {
+ theStatistics += theProf->GetDescription();
+ theStatistics += "\n";
+ }
+ }
+#endif // #ifdef PERFORM_PROFILE
+ if (m_ShowGUI)
+ CUICMessageBox::Show("Profiling Statistics", theStatistics, CUICMessageBox::ICON_INFO);
+ else {
+ std::cout << "Profiling Statistics"
+ << ": " << theStatistics.GetMulti() << std::endl;
+ }
+#endif
+}
+
+//==============================================================================
+/**
+ * Inform the user that the environment variables entered does not match the format
+ * expected, listing down all those settings that are wrong.
+ * @param inErrorMessage the listing of all those errors.
+ */
+void CDialogs::DisplayEnvironmentVariablesError(const Q3DStudio::CString &inErrorMessage)
+{
+ Q3DStudio::CString theTitle = ::LoadResourceString(IDS_ERROR_PROJECT_VARIABLES_TITLE);
+ Q3DStudio::CString theMessage = ::LoadResourceString(IDS_ERROR_PROJECT_VARIABLES_MSG);
+ theMessage += inErrorMessage;
+ theMessage += ::LoadResourceString(IDS_PROJECT_VARIABLES_FORMAT);
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theMessage, CUICMessageBox::ICON_ERROR, false,
+ qApp->activeWindow());
+ else {
+ std::cout << theTitle.GetCharStar() << ": " << theMessage.GetCharStar() << std::endl;
+ }
+}
+
+//==============================================================================
+/**
+ * Reset settings.
+ * Typically inCurrentDocPath is only set when Studio is first launched.
+ * @param inCurrentDocPath the current document path, if any. Application directory if
+ *there is none.
+ */
+void CDialogs::ResetSettings(const Q3DStudio::CString &inCurrentDocPath)
+{
+ // Initialize the default dir/paths to the current document path if specified, otherwise leave
+ // everything as it is.
+ if (!inCurrentDocPath.IsEmpty()) {
+ m_LastSaveFile = inCurrentDocPath;
+ }
+}
+
+bool CDialogs::DisplayResetKeyframeValuesDlg()
+{
+#ifdef KDAB_TEMPORARILY_REMOVED
+ CResetKeyframeValuesDlg theDialog;
+ return theDialog.DoModal() == IDOK;
+#endif
+ return false;
+}
+
+//==============================================================================
+/**
+ * User trying to do a pathological paste, such as pasting a component copied from a different
+ *instance
+ * of Studio into an instance of the same component that already exists in the current instance
+ *of Studio, and
+ * is potentially replaced and deleted.
+ */
+void CDialogs::DisplayPasteFailed()
+{
+ Q3DStudio::CString theTitle(::LoadResourceString(IDS_ERROR_PATHOLOGICAL_PASTE_TITLE));
+ Q3DStudio::CString theMessage(::LoadResourceString(IDS_ERROR_PATHOLOGICAL_PASTE_MESSAGE));
+
+ if (m_ShowGUI)
+ CUICMessageBox::Show(theTitle, theMessage, CUICMessageBox::ICON_ERROR, false,
+ qApp->activeWindow());
+ else
+ std::cout << theTitle.GetCharStar() << ": " << theMessage.GetCharStar() << std::endl;
+}
+
+//==============================================================================
+/**
+ * Video card OpenGL version is too low to be supported.
+ */
+void CDialogs::DisplayGLVersionError(const Q3DStudio::CString &inGLVersion,
+ const Q3DStudio::CString &inMinVersion)
+{
+ DisplayGLVersionDialog(inGLVersion, inMinVersion, true);
+}
+
+//==============================================================================
+/**
+ * Video card OpenGL version is outdated, but could be usable.
+ */
+void CDialogs::DisplayGLVersionWarning(const Q3DStudio::CString &inGLVersion,
+ const Q3DStudio::CString &inRecommendedVersion)
+{
+ DisplayGLVersionDialog(inGLVersion, inRecommendedVersion, false);
+}
+
+//==============================================================================
+/**
+ * Display the error dialog or warning dialog that OpenGL version is lower than what is
+ *expected
+ */
+void CDialogs::DisplayGLVersionDialog(const Q3DStudio::CString &inGLVersion,
+ const Q3DStudio::CString &inRecommendedVersion, bool inError)
+{
+ long theTitleResourceID;
+ long theMessageResourceID;
+
+ if (inError) {
+ theTitleResourceID = IDS_ERROR_MSGTITLE;
+ theMessageResourceID = IDS_GL_VERSION_ERROR;
+ } else {
+ theTitleResourceID = IDS_WARNING_MSGTITLE;
+ theMessageResourceID = IDS_GL_VERSION_WARNING;
+ }
+
+#ifdef KDAB_TEMPORARILY_REMOVED
+ Q3DStudio::CString theTitle(::LoadResourceString(theTitleResourceID));
+ Q3DStudio::CString theMessage(::LoadResourceString(theMessageResourceID));
+ Q3DStudio::CString theFormattedMessage;
+ theFormattedMessage.Format(theMessage, static_cast<const wchar_t *>(inGLVersion),
+ static_cast<const wchar_t *>(inRecommendedVersion));
+
+ CGLVersionDlg theGLVersionDlg;
+ theGLVersionDlg.Initialize(theTitle, theFormattedMessage, inError);
+ theGLVersionDlg.DoModal();
+
+ if (theGLVersionDlg.GetDontShowAgain())
+ CStudioPreferences::SetDontShowGLVersionDialog(true);
+#endif
+}
diff --git a/src/Authoring/Studio/_Win/Workspace/Views.cpp b/src/Authoring/Studio/_Win/Workspace/Views.cpp
new file mode 100644
index 00000000..50ab6f62
--- /dev/null
+++ b/src/Authoring/Studio/_Win/Workspace/Views.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2002 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Prefix
+//==============================================================================
+#include "stdafx.h"
+#include "Views.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "Doc.h"
+#endif
+#include "MainFrm.h"
+#ifdef KDAB_TEMPORARILY_REMOVED
+#include "TimelineTimelineLayout.h"
+#include "ScalableScroller.h"
+#include "PaletteManager.h"
+#include "HotKeys.h"
+#include "Dispatch.h"
+#include "ActionControl.h"
+#include "StudioPaletteBar.h"
+#endif
+
+//==============================================================================
+// Implementation
+//==============================================================================
+
+//=============================================================================
+/**
+ * Constructor
+ */
+CViews::CViews(CStudioApp * /*inStudioApp*/)
+ : m_MainFrame(nullptr)
+{
+}
+
+//=============================================================================
+/**
+ * Destructor
+ */
+CViews::~CViews()
+{
+ DestroyViews();
+}
+
+//=============================================================================
+/**
+ *
+ */
+void CViews::CreateViews()
+{
+ // To create the main window, this code creates a new frame window
+ // object and then sets it as the application's main window object
+ m_MainFrame = new CMainFrame();
+ m_MainFrame->show();
+#ifdef KDAB_TEMPORARILY_REMOVED
+ // create and load the frame with its resources
+ m_MainFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, nullptr, nullptr);
+
+ m_MainFrame->RestoreLayout();
+#endif
+}
+
+//=============================================================================
+/**
+ *
+ */
+void CViews::DestroyViews()
+{
+ if (m_MainFrame) {
+ // Do NOT use delete to destroy a CFrameWnd object! Use DestroyWindow() instead.
+ m_MainFrame->deleteLater();
+ m_MainFrame = nullptr;
+ }
+}
+
+//==============================================================================
+// Keyboard
+//==============================================================================
+
+//=============================================================================
+/**
+ * Register all Application specific shortcut keys.
+ * Used to map hotkeys that are active through the whole app, not just one
+ * view.
+ * @param inHotKeys the handler to register on.
+ */
+void CViews::RegisterGlobalKeyboardShortcuts(CHotKeys *inHotKeys)
+{
+ if (m_MainFrame)
+ m_MainFrame->RegisterGlobalKeyboardShortcuts(inHotKeys);
+}
+
+//=============================================================================
+/**
+ * NO ONE SHOULD USE THIS FUNCTION OTHER THAN THE MAINFRAME ON WINDOWS
+ */
+CMainFrame *CViews::GetMainFrame()
+{
+ return m_MainFrame;
+}
+
+//=============================================================================
+/**
+ *
+ */
+void CViews::RecheckMainframeSizingMode()
+{
+ if (m_MainFrame != nullptr)
+ m_MainFrame->RecheckSizingMode();
+}
+
+//==============================================================================
+// Static
+//==============================================================================
+
+//=============================================================================
+/**
+ * Creates a palette and the associated view.
+ * @param inClass Should be RUNTIME_CLASS( CCLASS ) where CCLASS is a class that
+ * inherits from MFC::CView (must implement dynamic creation) and is the view
+ * that you want associated with the palette.
+ * @param inPalette Palette that you want the view attached to
+ * @param inParent Parent window or nullptr for top level windows
+ * @param inWindowTitle Title caption to appear on the title bar of the palette
+ * @param inShowWindow true to show the window after creation, false to hide it
+ */
+#ifdef KDAB_TEMPORARILY_REMOVED
+void CViews::CreatePaletteAndView(CRuntimeClass *inClass, CStudioPaletteBar *inPalette,
+ CFrameWnd *inParent, Q3DStudio::CString inWindowTitle)
+{
+ CCreateContext theCreateContext;
+ memset(&theCreateContext, 0, sizeof(CCreateContext));
+ theCreateContext.m_pNewViewClass = inClass;
+ theCreateContext.m_pCurrentFrame = inParent;
+ theCreateContext.m_pCurrentDoc = nullptr;
+
+ inPalette->Create(::CString(inWindowTitle.GetMulti()), &theCreateContext,
+ CPaletteManager::GetUniquePaletteId(), inParent);
+}
+#endif
+
+//=============================================================================
+/**
+ * Creates a dialog and the associated view.
+ * @param inClass Should be RUNTIME_CLASS( CCLASS ) where CCLASS is a class that
+ * inherits from MFC::CView (must implement dynamic creation) and is the view
+ * that you want associated with the palette.
+ * @param inPalette Palette that you want the view attached to
+ * @param inParent Parent window or nullptr for top level windows
+ * @param inWindowTitle Title caption to appear on the title bar of the palette
+ * @param inShowWindow true to show the window after creation, false to hide it
+ */
+#ifdef KDAB_TEMPORARILY_REMOVED
+void CViews::CreateDialogAndView(CRuntimeClass *inClass, CStudioDialog *inDialog,
+ CFrameWnd *inParent, Q3DStudio::CString inWindowTitle)
+{
+ CCreateContext theCreateContext;
+ memset(&theCreateContext, 0, sizeof(CCreateContext));
+ theCreateContext.m_pNewViewClass = inClass;
+ theCreateContext.m_pCurrentFrame = inParent;
+ theCreateContext.m_pCurrentDoc = nullptr;
+
+ inDialog->Create(::CString(inWindowTitle.GetMulti()), &theCreateContext, inParent);
+}
+#endif