aboutsummaryrefslogtreecommitdiff
path: root/tools/ArtistTools/source/CoreLib/Window
diff options
context:
space:
mode:
Diffstat (limited to 'tools/ArtistTools/source/CoreLib/Window')
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/AppMainWindow.cpp1448
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/AppMainWindow.h208
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.cpp106
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.h31
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/D3DWidget.cpp151
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/D3DWidget.h51
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.cpp263
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.h47
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.cpp177
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.h80
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.cpp906
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.h100
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.cpp93
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.h39
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.cpp190
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.h51
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/OutputWindow.cpp22
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/OutputWindow.h22
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.cpp17
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.h284
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/SlideSpinBoxInt.h15
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/TipListView.cpp42
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/TipListView.h26
-rw-r--r--tools/ArtistTools/source/CoreLib/Window/UIGlobal.h37
24 files changed, 4406 insertions, 0 deletions
diff --git a/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.cpp b/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.cpp
new file mode 100644
index 0000000..3a85d8b
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.cpp
@@ -0,0 +1,1448 @@
+#include <QtWidgets/QShortcut>
+#include <QtWidgets/QAction>
+#include <QtWidgets/QMenu>
+#include <QtWidgets/QFileDialog>
+#include <QtWidgets/QMessageBox>
+#include <QtGui/QDesktopServices>
+#include <QtWidgets/QScrollBar>
+#include <QtWidgets/QGraphicsEllipseItem>
+#include <QtWidgets/QGraphicsView>
+#include <QtWidgets/QProgressDialog>
+
+#include <Windows.h>
+
+#include "AppMainWindow.h"
+#include "ExpandablePanel.h"
+
+#include "D3DWidget.h"
+
+#include "DisplayMeshesPanel.h"
+
+#include "DisplayPreferencesPanel.h"
+#include "DisplayScenePanel.h"
+#include "DisplayLightPanel.h"
+#include "ui_DisplayPreferencesPanel.h"
+#include "ui_DisplayScenePanel.h"
+#include "ui_DisplayLightPanel.h"
+#include "CameraBookmarksDialog.h"
+
+#include "SimpleScene.h"
+#include "GlobalSettings.h"
+
+#include "ViewerOutput.h"
+#include "Gamepad.h"
+#if USE_CURVE_EDITOR
+#include "CurveEditorMainWindow.h"
+#endif
+#ifndef NV_ARTISTTOOLS
+#include "ui_AppMainToolbar.h"
+#include "ui_AssetControlPanel.h"
+#include "ui_GeneralAttributesPanel.h"
+#include "ui_PhysicalMaterialsPanel.h"
+#include "ui_StyleMaterialsPanel.h"
+#include "ui_GraphicalMaterialsPanel.h"
+#include "BlastToolbar.h"
+#include "AssetControlPanel.h"
+#include "GraphicalMaterialPanel.h"
+#include "PhysicalMaterialPanel.h"
+#include "StyleMaterialPanel.h"
+#include "GeneralAttributePanel.h"
+#include "MaterialSetPanel.h"
+#include "LodPanel.h"
+#include "DisplayVisualizersPanel.h"
+#include "ui_DisplayVisualizersPanel.h"
+#include "DisplayMeshMaterialsPanel.h"
+#include "FurCharacter.h"
+#include "HairParams.h"
+#include "AboutDialog.h"
+#else
+#endif // NV_ARTISTTOOLS
+
+class MsgPrinter : public FrontPrinter
+{
+public:
+ MsgPrinter(QTextBrowser* browser):_browser(browser)
+ {
+
+ }
+
+ void print(const char* txt, unsigned long color /* = 0 */, Effect e /* = NONE */)
+ {
+ if(color == 0 && e == FrontPrinter::NONE)
+ {
+ _browser->insertPlainText(QString(txt)+"\n");
+ }
+ else
+ {
+ // output html text
+ QString surfix;
+ QString postfix;
+ surfix.reserve(64);
+ postfix.reserve(64);
+ if(e & FrontPrinter::BOLD)
+ {
+ surfix = surfix + "<b>";
+ postfix= postfix + "</b>";
+ }
+ else if(e & FrontPrinter::UNDERLINE)
+ {
+ surfix = surfix + "<u>";
+ postfix= QString("</u>") + postfix;
+ }
+ else if(e & FrontPrinter::ITALIC)
+ {
+ surfix = surfix + "<i>";
+ postfix= QString("</i>") + postfix;
+ }
+
+ if(color != 0)
+ {
+ int r = GetRValue(color);
+ int g = GetGValue(color);
+ int b = GetBValue(color);
+
+ surfix = QString("<div style=\"color:rgb(%1,%2,%3);\">").arg(r).arg(g).arg(b) + surfix;
+ postfix= postfix + QString("</div><br />");
+ }
+
+ QString html = surfix + QString(txt) + postfix;
+ _browser->insertHtml(html);
+ }
+ // auto scroll to the bottom
+ QScrollBar *sb = _browser->verticalScrollBar();
+ if (sb) sb->setValue(sb->maximum());
+ }
+
+private:
+ QTextBrowser* _browser;
+};
+
+int AppMainWindow::_connectionMode = 0;
+bool AppMainWindow::_expertMode = false;
+AppMainWindow* gAppMainWindow = NV_NULL;
+
+void CreateAppMainWindow()
+{
+ gAppMainWindow = new AppMainWindow;
+}
+
+void ReleaseAppMainWindow()
+{
+ delete gAppMainWindow;
+ gAppMainWindow = NV_NULL;
+}
+
+AppMainWindow& AppMainWindow::Inst()
+{
+ return *gAppMainWindow;
+}
+
+AppMainWindow::AppMainWindow(QWidget *parent, Qt::WindowFlags flags)
+ : QMainWindow(parent, flags)
+ , _bookmarksMenu(0)
+ ,_displayMeshesPanel(0)
+ , _displayPreferencesPanel(0)
+ , _displayScenePanel(0)
+ ,_displayLightPanel(0)
+#if USE_CURVE_EDITOR
+ ,_curveEditorInitizlized(false)
+ , _curveEditorMainWindow(nullptr)
+#endif
+ ,_bookmarkActionGroup(0)
+ ,_actionAddBookmark(0)
+ ,_actionEditBookmarks(0)
+{
+ setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
+ setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+
+ ui.setupUi(this);
+ //ui.dockOutputWindow->hide();
+
+#ifndef NV_ARTISTTOOLS
+ _mainToolbar = 0;
+ _physicalMaterialPanel = 0;
+ _styleMaterialPanel = 0;
+ _graphicalMaterialPanel = 0;
+ _displayFurVisualizersPanel = 0;
+ _assetControlPanel = 0;
+ _generalAttributePanel = 0;
+ _lodPanel = 0;
+ _displayMeshMaterialsPanel;
+#if USE_MATERIAL_SET
+ _materialSetPanel = 0;
+#endif
+#else
+ CoreLib::Inst()->AppMainWindow_AppMainWindow();
+#endif // NV_ARTISTTOOLS
+
+ _progressDialog.close(); // prevent show one empty progress dialog when it runs.
+
+ m_bGizmoWithLocal = false;
+}
+
+void AppMainWindow::InitUI()
+{
+ _d3dWidget = new D3DWidget(this);
+ _d3dWidget->setMinimumSize(200, 200);
+ ui.renderLayout->addWidget(_d3dWidget);
+
+ InitShortCuts();
+ InitMenuItems();
+ InitToolbar();
+ InitPluginTab();
+ InitMainTab();
+
+ InitMouseSchemes();
+
+ updateUI();
+
+ if (_connectionMode == 1) // master mode
+ ui.sideBarTab->removeTab(1);
+
+ if (_connectionMode == 2)
+ ui.sideBarTab->removeTab(0);
+
+
+ QString defFilePath;
+
+ QString appDir = qApp->applicationDirPath();
+ QDir dir(appDir);
+ if (dir.cd("../../media"))
+ defFilePath = dir.absolutePath();
+
+ _lastFilePath = defFilePath;
+
+ _navigationStyle = 0;
+
+ // initialize the message printer
+ _printer = new MsgPrinter(this->ui.outputWindow);
+ ViewerOutput::Inst().RegisterPrinter(_printer);
+
+#ifndef NV_ARTISTTOOLS
+
+ viewer_info(
+ "<a href=\"https://developer.nvidia.com/hairworks\" style=\"color:rgb(118,180,0);\">NVIDIA Blast Version v"
+ NV_HAIR_RELEASE_VERSION_STRING
+ "</a>");
+
+#else
+ CoreLib::Inst()->AppMainWindow_InitUI();
+#endif // NV_ARTISTTOOLS
+}
+
+AppMainWindow::~AppMainWindow()
+{
+}
+
+void AppMainWindow::setConnectionMode(int m)
+{
+ _connectionMode = m;
+}
+
+void AppMainWindow::startProgress()
+{
+ _progressDialog.setWindowModality(Qt::WindowModal);
+ _progressDialog.show();
+}
+
+void AppMainWindow::setProgress(const char* label, int progress)
+{
+ _progressDialog.setLabelText(label);
+ if (progress >= 0)
+ _progressDialog.setValue(progress);
+
+ _progressDialog.update();
+}
+
+void AppMainWindow::endProgress()
+{
+ _progressDialog.close();
+}
+
+void AppMainWindow::quit()
+{
+ emit aboutToQuit();
+}
+
+void AppMainWindow::setProgressMaximum(int m)
+{
+ _progressDialog.setMaximum(m);
+}
+
+void AppMainWindow::InitMenuItems()
+{
+ QMenuBar* menu = ui.menuBar;
+ QAction* act = NV_NULL;
+
+ // file sub-menu
+ QMenu* fileMenu = menu->addMenu("&File");
+
+ if (_connectionMode != 1)
+ {
+ act = new QAction("Clear scene", this);
+ act->setShortcut(QKeySequence::New);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_clearScene()));
+ fileMenu->addAction(act);
+
+ fileMenu->addSeparator();
+
+ act = new QAction("Open fbx file", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_openfbx()));
+ fileMenu->addAction(act);
+
+ fileMenu->addSeparator();
+
+#ifndef NV_ARTISTTOOLS
+ fileMenu->addSeparator();
+ act = new QAction("Open project file", this);
+ act->setShortcut(QKeySequence::Open);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_openProject()));
+ fileMenu->addAction(act);
+
+ act = new QAction("Save project file", this);
+ act->setShortcut(QKeySequence::Save);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveProject()));
+ fileMenu->addAction(act);
+
+ act = new QAction("Save project file as...", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveProjectAs()));
+ fileMenu->addAction(act);
+
+ fileMenu->addSeparator();
+
+ act = new QAction("&Open hair file", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_openHair()));
+ fileMenu->addAction(act);
+
+ act = new QAction("&Save hair file", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveHair()));
+ fileMenu->addAction(act);
+
+ act = new QAction("Save hair file as...", this);
+ act->setShortcut(QKeySequence::SaveAs);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveHairAs()));
+ fileMenu->addAction(act);
+
+ act = new QAction("Save all hairs...", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_saveAllHairs()));
+ fileMenu->addAction(act);
+
+ fileMenu->addSeparator();
+#else
+ CoreLib::Inst()->AppMainWindow_InitMenuItems(ui.menuBar);
+#endif // NV_ARTISTTOOLS
+ }
+
+ act = new QAction("E&xit", this);
+ act->setShortcut(QKeySequence::Quit);
+ connect(act, SIGNAL(triggered()), this, SLOT(close()));
+ fileMenu->addAction(act);
+
+ // view submenu
+ QMenu* viewMenu = menu->addMenu("&View");
+ act = new QAction("Bookmarks", this);
+ //connect(act, SIGNAL(triggered()), this, SLOT(menu_showOutput()));
+ viewMenu->addAction(act);
+ _bookmarksMenu = new QMenu("Bookmarks", this);
+ connect(_bookmarksMenu, SIGNAL(triggered(QAction*)), this, SLOT(menu_bookmarkTriggered(QAction*)));
+ act->setMenu(_bookmarksMenu);
+ act = new QAction("Add Bookmark", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_addBookmark()));
+ _bookmarksMenu->addAction(act);
+ _actionAddBookmark = act;
+ act = new QAction("Edit Bookmarks", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_editBookmarks()));
+ _bookmarksMenu->addAction(act);
+ _actionEditBookmarks = act;
+ _bookmarksMenu->addSeparator();
+ _bookmarkActionGroup = new QActionGroup(this);
+
+ // window submenu
+ QMenu* windowMenu = menu->addMenu("&Window");
+ act = new QAction("Output", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_showOutput()));
+ windowMenu->addAction(act);
+
+ act = new QAction("Attribute Editor", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_showAttributeEditor()));
+ windowMenu->addAction(act);
+
+#if USE_CURVE_EDITOR
+ act = new QAction("Curve Editor", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_showCurveEditor()));
+ windowMenu->addAction(act);
+#endif
+
+ // help submenu
+ QMenu* helpMenu = menu->addMenu("&Help");
+
+ act = new QAction("Documentation", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_opendoc()));
+ helpMenu->addAction(act);
+
+ act = new QAction("&About", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(menu_about()));
+ helpMenu->addAction(act);
+}
+
+void AppMainWindow::InitToolbar()
+{
+ if (_connectionMode != 1)
+ {
+#ifndef NV_ARTISTTOOLS
+ _mainToolbar = new BlastToolbar(ui.centralWidget);
+ ui.verticalLayout->insertWidget(0, _mainToolbar);
+ connect(_mainToolbar->getUI().btnFileOpen, SIGNAL(clicked()), this, SLOT(menu_openProject()));
+#else
+ CoreLib::Inst()->AppMainWindow_InitToolbar(ui.centralWidget, ui.verticalLayout);
+#endif // NV_ARTISTTOOLS
+ }
+}
+
+void AppMainWindow::InitPluginTab()
+{
+#ifndef NV_ARTISTTOOLS
+ QWidget *tabFur;
+ QGridLayout *gridLayout;
+ QFrame *furMaterialEditorArea;
+ QVBoxLayout *furMaterialEditorAreaLayout;
+ QScrollArea *furScrollArea;
+ QWidget *furScrollAreaContents;
+ QVBoxLayout *furScrollAreaLayout;
+ QSpacerItem *verticalSpacer;
+
+ tabFur = new QWidget();
+ tabFur->setObjectName(QStringLiteral("tabFur"));
+ gridLayout = new QGridLayout(tabFur);
+ gridLayout->setSpacing(6);
+ gridLayout->setContentsMargins(11, 11, 11, 11);
+ gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setContentsMargins(0, 0, 0, 0);
+ furMaterialEditorArea = new QFrame(tabFur);
+ furMaterialEditorArea->setObjectName(QStringLiteral("furMaterialEditorArea"));
+ furMaterialEditorAreaLayout = new QVBoxLayout(furMaterialEditorArea);
+ furMaterialEditorAreaLayout->setSpacing(6);
+ furMaterialEditorAreaLayout->setContentsMargins(11, 11, 11, 11);
+ furMaterialEditorAreaLayout->setObjectName(QStringLiteral("furMaterialEditorAreaLayout"));
+ furMaterialEditorAreaLayout->setContentsMargins(2, 2, 2, 2);
+
+ gridLayout->addWidget(furMaterialEditorArea, 1, 0, 1, 1);
+
+ furScrollArea = new QScrollArea(tabFur);
+ furScrollArea->setObjectName(QStringLiteral("furScrollArea"));
+ furScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ furScrollArea->setWidgetResizable(true);
+ furScrollAreaContents = new QWidget();
+ furScrollAreaContents->setObjectName(QStringLiteral("furScrollAreaContents"));
+ furScrollAreaContents->setGeometry(QRect(0, 0, 359, 481));
+ furScrollAreaLayout = new QVBoxLayout(furScrollAreaContents);
+ furScrollAreaLayout->setSpacing(3);
+ furScrollAreaLayout->setContentsMargins(11, 11, 11, 11);
+ furScrollAreaLayout->setObjectName(QStringLiteral("furScrollAreaLayout"));
+ furScrollAreaLayout->setContentsMargins(2, 2, 2, 2);
+ verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
+
+ furScrollAreaLayout->addItem(verticalSpacer);
+
+ furScrollArea->setWidget(furScrollAreaContents);
+
+ gridLayout->addWidget(furScrollArea, 0, 0, 1, 1);
+
+ ui.sideBarTab->addTab(tabFur, QString());
+
+ ui.sideBarTab->setTabText(ui.sideBarTab->indexOf(tabFur), QApplication::translate("AppMainWindowClass", "Hair", 0));
+
+ ExpandablePanel* panel = 0;
+ int pannelCnt = 0;
+
+ if (_connectionMode == 0)
+ {
+ panel = new ExpandablePanel(furScrollAreaContents, false);
+ _generalAttributePanel = new GeneralAttributePanel(panel);
+ panel->AddContent(_generalAttributePanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Asset Selection");
+
+ panel = new ExpandablePanel(furScrollAreaContents, false);
+ _assetControlPanel = new AssetControlPanel(panel);
+ panel->AddContent(_assetControlPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("General Settings");
+
+ }
+
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _displayFurVisualizersPanel = new DisplayFurVisualizersPanel(panel);
+ panel->AddContent(_displayFurVisualizersPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Visualization");
+
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _physicalMaterialPanel = new PhysicalMaterialPanel(panel);
+ panel->AddContent(_physicalMaterialPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Physical");
+
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _styleMaterialPanel = new StyleMaterialPanel(panel);
+ panel->AddContent(_styleMaterialPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Style");
+
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _graphicalMaterialPanel = new GraphicalMaterialPanel(panel);
+ panel->AddContent(_graphicalMaterialPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Graphics");
+
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _lodPanel = new LodPanel(panel);
+ panel->AddContent(_lodPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Level Of Detail");
+
+#if USE_MATERIAL_SET
+ panel = new ExpandablePanel(furScrollAreaContents);
+ _materialSetPanel = new MaterialSetPanel(panel);
+ panel->AddContent(_materialSetPanel);
+ furScrollAreaLayout->insertWidget(pannelCnt++, panel);
+ panel->SetTitle("Control Texture Channels");
+ //_materialSetPanel->hide();
+ //panel->SetCollapsed(true);
+#else
+ ui.furMaterialEditorAreaLayout->setEnabled(false);
+#endif
+#else
+ CoreLib::Inst()->AppMainWindow_InitPluginTab(ui.sideBarTab);
+#endif // NV_ARTISTTOOLS
+
+#if USE_CURVE_EDITOR
+ _curveEditorMainWindow = new nvidia::CurveEditor::CurveEditorMainWindow( this);//nullptr);
+ _curveEditorMainWindow->setResampleEnabled(false);
+ ui.dockWidgetCurveEditor->setWidget(_curveEditorMainWindow);
+ ui.dockWidgetCurveEditor->setWindowTitle(tr("Curve Editor"));
+
+ connect(_curveEditorMainWindow, SIGNAL(CurveAttributeChanged(nvidia::CurveEditor::CurveAttribute*)), this, SLOT(onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute*)));
+ connect(_curveEditorMainWindow, SIGNAL(ColorAttributeChanged(nvidia::CurveEditor::ColorAttribute*)), this, SLOT(onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute*)));
+ connect(_curveEditorMainWindow, SIGNAL(ReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute*, bool, int)), this, SLOT(onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute*, bool, int)));
+//#else
+// ui.furCurveEditorAreaLayout->setEnabled(false);
+#endif
+}
+
+void AppMainWindow::InitMainTab()
+{
+ int idx = 0;
+
+ if (_connectionMode != 1)
+ {
+ ExpandablePanel* panel = new ExpandablePanel(ui.displayScrollAreaContents);
+ _displayPreferencesPanel = new DisplayPreferencesPanel(panel);
+ panel->AddContent(_displayPreferencesPanel);
+ ui.displayScrollAreaLayout->insertWidget(idx++, panel);
+ panel->SetTitle("Preferences");
+
+ panel = new ExpandablePanel(ui.displayScrollAreaContents);
+ _displayScenePanel = new DisplayScenePanel(panel);
+ panel->AddContent(_displayScenePanel);
+ ui.displayScrollAreaLayout->insertWidget(idx++, panel);
+ panel->SetTitle("Scene");
+
+ panel = new ExpandablePanel(ui.displayScrollAreaContents);
+ _displayLightPanel = new DisplayLightPanel(panel);
+ panel->AddContent(_displayLightPanel);
+ ui.displayScrollAreaLayout->insertWidget(idx++, panel);
+ panel->SetTitle("Light");
+
+ panel = new ExpandablePanel(ui.displayScrollAreaContents);
+ _displayMeshesPanel = new DisplayMeshesPanel(panel);
+ panel->AddContent(_displayMeshesPanel);
+ ui.displayScrollAreaLayout->insertWidget(idx++, panel);
+ panel->SetTitle("Display Meshes");
+ }
+
+ if (_connectionMode != 1)
+ {
+#ifndef NV_ARTISTTOOLS
+ ExpandablePanel* panel = new ExpandablePanel(ui.displayScrollAreaContents);
+ _displayMeshMaterialsPanel = new DisplayMeshMaterialsPanel(panel);
+ panel->AddContent(_displayMeshMaterialsPanel);
+ ui.displayScrollAreaLayout->insertWidget(idx++, panel);
+ panel->SetTitle("Display Mesh Materials");
+#else
+ CoreLib::Inst()->AppMainWindow_InitMainTab(ui.displayScrollAreaContents, ui.displayScrollAreaLayout, idx);
+#endif // NV_ARTISTTOOLS
+ }
+}
+
+void AppMainWindow::InitShortCuts()
+{
+ QShortcut* shortCut;
+ shortCut = new QShortcut(QKeySequence(Qt::Key_F), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_frameall()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_H), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_hud()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_G), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_statistics()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_Space), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_pause()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_B), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_reset()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_Escape), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_escape()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_V), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_expert()));
+
+ shortCut = new QShortcut(QKeySequence("Ctrl+X"), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_expert()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_D), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(demo_next()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_Right), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(demo_next()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_A), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(demo_prev()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_Left), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(demo_prev()));
+
+ shortCut = new QShortcut(QKeySequence(Qt::Key_F2), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_output()));
+
+ shortCut = new QShortcut(QKeySequence("Ctrl+F"), this);
+ connect(shortCut, SIGNAL(activated()), this, SLOT(shortcut_fitcamera()));
+}
+
+//////////////////////////////////////////////////////////////////////////
+void AppMainWindow::updateBookmarkMenu()
+{
+ // clear old menu items of camera bookmarks
+ while (_bookmarkActionGroup->actions().size() > 0)
+ {
+ QAction* act = _bookmarkActionGroup->actions()[0];
+ _bookmarkActionGroup->removeAction(act);
+ delete act;
+ }
+ _bookmarksMenu->clear();
+ _bookmarksMenu->addAction(_actionAddBookmark);
+ _bookmarksMenu->addAction(_actionEditBookmarks);
+ _bookmarksMenu->addSeparator();
+
+ QList<QString> bookmarks = SimpleScene::Inst()->getBookmarkNames();
+ int numBookmarks = bookmarks.size();
+ for (int i = 0; i < numBookmarks; ++i)
+ {
+ QString bookmark = bookmarks[i];
+
+ QAction* act = new QAction(bookmark, this);
+ act->setCheckable(true);
+ _bookmarksMenu->addAction(act);
+ _bookmarkActionGroup->addAction(act);
+ }
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+void AppMainWindow::updateUI()
+{
+ if (_bookmarksMenu && _bookmarkActionGroup)
+ {
+ updateBookmarkMenu();
+ }
+
+#ifndef NV_ARTISTTOOLS
+ if (_mainToolbar)
+ _mainToolbar->updateValues();
+
+ if (_graphicalMaterialPanel)
+ _graphicalMaterialPanel->updateValues();
+
+ if (_physicalMaterialPanel)
+ _physicalMaterialPanel->updateValues();
+
+ if (_styleMaterialPanel)
+ _styleMaterialPanel->updateValues();
+
+ if (_displayFurVisualizersPanel)
+ _displayFurVisualizersPanel->updateValues();
+
+ if (_lodPanel)
+ _lodPanel->updateValues();
+
+ if (_generalAttributePanel)
+ _generalAttributePanel->updateValues();
+
+ if (_assetControlPanel)
+ _assetControlPanel->updateValues();
+
+ if (_displayMeshMaterialsPanel)
+ _displayMeshMaterialsPanel->updateValues();
+
+#if USE_MATERIAL_SET
+ if (_materialSetPanel)
+ _materialSetPanel->updateValues();
+#endif
+#else
+ CoreLib::Inst()->AppMainWindow_updateUI();
+#endif // NV_ARTISTTOOLS
+
+ if (_displayPreferencesPanel)
+ _displayPreferencesPanel->updateValues();
+
+ if (_displayScenePanel)
+ _displayScenePanel->updateValues();
+
+ if (_displayLightPanel)
+ _displayLightPanel->updateValues();
+
+ if (_displayMeshesPanel)
+ _displayMeshesPanel->updateValues();
+
+#if USE_CURVE_EDITOR
+ if (_curveEditorMainWindow)
+ UpdateCurveEditor();
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////
+void AppMainWindow::updatePluginUI()
+{
+ SimpleScene::Inst()->setIsUpdatingUI(true);
+
+#ifndef NV_ARTISTTOOLS
+ if (_graphicalMaterialPanel)
+ _graphicalMaterialPanel->updateValues();
+
+ if (_physicalMaterialPanel)
+ _physicalMaterialPanel->updateValues();
+
+ if (_styleMaterialPanel)
+ _styleMaterialPanel->updateValues();
+
+ if (_lodPanel)
+ _lodPanel->updateValues();
+
+ if (_displayFurVisualizersPanel)
+ _displayFurVisualizersPanel->updateValues();
+
+ if (_generalAttributePanel)
+ _generalAttributePanel->updateValues();
+
+ if (_assetControlPanel)
+ _assetControlPanel->updateValues();
+
+#if USE_MATERIAL_SET
+ if (_materialSetPanel)
+ _materialSetPanel->updateValues();
+#endif
+#else
+ CoreLib::Inst()->AppMainWindow_updatePluginUI();
+#endif // NV_ARTISTTOOLS
+
+#if USE_CURVE_EDITOR
+ if (_curveEditorMainWindow)
+ UpdateCurveEditor();
+#endif
+
+ SimpleScene::Inst()->setIsUpdatingUI(false);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// event handlers
+
+
+//////////////////////////////////////////////////////////////////////////
+// event handlers
+bool AppMainWindow::openProject(QString fileName)
+{
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file= fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->LoadProject(dir, file) == false)
+ {
+ QMessageBox messageBox;
+ messageBox.critical(0,"Error","File open error!");
+ messageBox.setFixedSize(500,200);
+
+ AppMainWindow::Inst().endProgress();
+ char message[1024];
+ sprintf(message, "Failed to open project file(\"%s\")", (const char*)file);
+ viewer_err(message);
+ return false;
+ }
+
+ AppMainWindow::Inst().endProgress();
+ _lastFilePath = fileInfo.absoluteDir().absolutePath();
+
+ updateUI();
+ return true;
+ }
+ return false;
+}
+
+void AppMainWindow::processDragAndDrop(QString fname)
+{
+ openProject(fname);
+}
+
+void AppMainWindow::removeBookmark(const QString& name)
+{
+ QList<QAction*> bookmarks = _bookmarkActionGroup->actions();
+ int bookmarkCount = bookmarks.size();
+ for (int i = 0; i < bookmarkCount; ++i)
+ {
+ QAction* act = bookmarks.at(i);
+ if (act->text() == name)
+ {
+ _bookmarkActionGroup->removeAction(act);
+ _bookmarksMenu->removeAction(act);
+ delete act;
+ }
+ }
+}
+
+void AppMainWindow::renameBookmark(const QString& oldName, const QString& newName)
+{
+ QList<QAction*> bookmarks = _bookmarkActionGroup->actions();
+ int bookmarkCount = bookmarks.size();
+ for (int i = 0; i < bookmarkCount; ++i)
+ {
+ QAction* act = bookmarks.at(i);
+ if (act->text() == oldName)
+ {
+ act->setText(newName);
+ }
+ }
+}
+
+#if USE_CURVE_EDITOR
+void AppMainWindow::UpdateCurveEditor()
+{
+#ifndef NV_ARTISTTOOLS
+ _curveEditorMainWindow->setCurveAttributes(SimpleScene::Inst()->GetFurCharacter().GetCurveAttributes());
+ _curveEditorMainWindow->setColorCurveAttributes(SimpleScene::Inst()->GetFurCharacter().GetColorAttributes());
+#else
+ CoreLib::Inst()->AppMainWindow_UpdateCurveEditor();
+#endif // NV_ARTISTTOOLS
+
+ _curveEditorMainWindow->update();
+}
+
+void AppMainWindow::ShowCurveEditor(int paramId)
+{
+#ifndef NV_ARTISTTOOLS
+ _curveEditorMainWindow->setCurveAttributes(SimpleScene::Inst()->GetFurCharacter().GetCurveAttributes());
+ _curveEditorMainWindow->setColorCurveAttributes(SimpleScene::Inst()->GetFurCharacter().GetColorAttributes());
+ if (HAIR_PARAMS_ROOT_COLOR == paramId || HAIR_PARAMS_TIP_COLOR == paramId)
+ {
+ std::vector<nvidia::CurveEditor::ColorAttribute*> attributes = SimpleScene::Inst()->GetFurCharacter().GetColorAttributesByParamId(paramId);
+ _curveEditorMainWindow->setSelectedColorAttribute(attributes.size() > 0 ? attributes[0] : nullptr);
+ }
+ else
+ _curveEditorMainWindow->setSelectedCurveAttributes(SimpleScene::Inst()->GetFurCharacter().GetCurveAttributesByParamId(paramId));
+
+#else
+ CoreLib::Inst()->AppMainWindow_ShowCurveEditor(paramId);
+#endif // NV_ARTISTTOOLS
+
+ _curveEditorMainWindow->update();
+}
+#endif
+
+void AppMainWindow::menu_clearScene()
+{
+ SimpleScene::Inst()->Clear();
+ updateUI();
+}
+
+bool AppMainWindow::menu_openfbx()
+{
+ /*
+ QString lastDir = _lastFilePath;
+ QString fileName = QFileDialog::getOpenFileName(this, "Open FBX File", lastDir, "FBX File (*.fbx)");
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file= fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->LoadSceneFromFbx(dir, file) == false)
+ {
+ QMessageBox messageBox;
+ messageBox.critical(0,"Error","File open error!");
+ messageBox.setFixedSize(500,200);
+
+ AppMainWindow::Inst().endProgress();
+
+ char message[1024];
+ sprintf(message, "Failed to open fbx file(\"%s\")", (const char*)file);
+ viewer_err(message);
+
+ return false;
+ }
+
+ AppMainWindow::Inst().endProgress();
+
+ _lastFilePath = fileInfo.absoluteDir().absolutePath();
+
+ updateUI();
+
+ return true;
+ }
+ return true;
+ */
+
+ // dir and file will get in blast open asset dialog
+ return SimpleScene::Inst()->LoadSceneFromFbx("", "");
+}
+
+void AppMainWindow::menu_addBookmark()
+{
+ QString bookmark = SimpleScene::Inst()->createBookmark();
+
+ QAction* act = new QAction(bookmark, this);
+ act->setCheckable(true);
+ _bookmarksMenu->addAction(act);
+ _bookmarkActionGroup->addAction(act);
+ act->setChecked(true);
+}
+
+void AppMainWindow::menu_editBookmarks()
+{
+ CameraBookmarksDialog dlg(this);
+ dlg.exec();
+}
+
+void AppMainWindow::menu_bookmarkTriggered(QAction* act)
+{
+ if (_actionAddBookmark != act && _actionEditBookmarks != act)
+ {
+ SimpleScene::Inst()->activateBookmark(act->text());
+ }
+}
+
+void AppMainWindow::menu_showOutput()
+{
+ bool bVisibal = ui.dockOutputWindow->isVisible();
+ ui.dockOutputWindow->setVisible(!bVisibal);
+}
+
+void AppMainWindow::menu_showAttributeEditor()
+{
+ bool bVisibal = ui.dockWidget->isVisible();
+ ui.dockWidget->setVisible(!bVisibal);
+}
+#if USE_CURVE_EDITOR
+void AppMainWindow::menu_showCurveEditor()
+{
+ bool bVisibal = ui.dockWidgetCurveEditor->isVisible();
+ ui.dockWidgetCurveEditor->setVisible(!bVisibal);
+}
+#endif
+void AppMainWindow::menu_about()
+{
+ qDebug("%s", __FUNCTION__);
+#ifndef NV_ARTISTTOOLS
+ AboutDialog::ShowAboutDialog();
+#else
+ CoreLib::Inst()->AppMainWindow_menu_about();
+#endif // NV_ARTISTTOOLS
+}
+
+void AppMainWindow::menu_opendoc()
+{
+ qDebug("%s", __FUNCTION__);
+
+#ifndef NV_ARTISTTOOLS
+ QString appDir = QApplication::applicationDirPath();
+ QString docsFile = QFileInfo(appDir + "/../../docs/User_Guide/Nvidia Blast.chm").absoluteFilePath();
+
+ QUrl docsUrl = QUrl::fromLocalFile(docsFile);
+ QUrl url = QUrl::fromUserInput(QString("http://docs.nvidia.com/gameworks/content/artisttools/hairworks/index.html"));
+ QDesktopServices::openUrl(url);
+#else
+ CoreLib::Inst()->AppMainWindow_menu_opendoc();
+#endif // NV_ARTISTTOOLS
+}
+
+void AppMainWindow::shortcut_frameall()
+{
+ qDebug("ShortCut_F: frame all");
+}
+
+void AppMainWindow::shortcut_hud()
+{
+ Gamepad::ShowHideHud();
+ qDebug("ShortCut_S: statistics on/off");
+}
+
+void AppMainWindow::shortcut_statistics()
+{
+ Gamepad::ShowHideStats();
+ qDebug("ShortCut_S: statistics on/off");
+}
+
+void AppMainWindow::shortcut_reset()
+{
+ Gamepad::ResetAnimation();
+}
+
+void AppMainWindow::shortcut_pause()
+{
+ //_mainToolbar->on_btnPlayAnimation_clicked(); // this one has some delay
+ //qDebug("ShortCut_Space: play/pause simualtion");
+ Gamepad::PlayPauseAnimation();
+}
+
+bool AppMainWindow::IsExpertMode()
+{
+ return _expertMode;
+}
+
+void AppMainWindow::demo_next()
+{
+ Gamepad::DemoNext();
+}
+
+void AppMainWindow::demo_prev()
+{
+ Gamepad::DemoPrev();
+}
+
+void AppMainWindow::shortcut_escape()
+{
+ Gamepad::DemoEscape();
+}
+
+void AppMainWindow::shortcut_expert()
+{
+ qDebug("ShortCut_F: expert mode on/off");
+
+ _expertMode = !_expertMode;
+ bool mode = !_expertMode;
+
+ ui.menuBar->setVisible(mode);
+ ui.dockWidget->setVisible(mode);
+ ui.dockOutputWindow->setVisible(mode);
+#if USE_CURVE_EDITOR
+ ui.dockWidgetCurveEditor->setVisible(mode);
+#endif
+ ui.statusBar->setVisible(mode);
+
+#ifndef NV_ARTISTTOOLS
+ if (_mainToolbar)
+ _mainToolbar->setVisible(mode);
+#else
+ CoreLib::Inst()->AppMainWindow_shortcut_expert(mode);
+#endif // NV_ARTISTTOOLS
+
+ //bool bDemoMode = AppMainWindow::IsExpertMode();
+ bool bMaxSized = AppMainWindow::Inst().isMaximized();
+ if (!bMaxSized)
+ {
+ // resize before change to demo mode
+ AppMainWindow::Inst().showMaximized();
+ }
+
+ _d3dWidget->update();
+ Gamepad::ShowProjectName();
+}
+
+void AppMainWindow::shortcut_output()
+{
+ ui.dockOutputWindow->show();
+ _d3dWidget->update();
+}
+
+void AppMainWindow::shortcut_meshmat()
+{
+}
+
+void AppMainWindow::shortcut_fitcamera()
+{
+ qDebug("ShortCut_Ctrl+F: fit camera");
+ SimpleScene::Inst()->FitCamera();
+}
+
+#if USE_CURVE_EDITOR
+void AppMainWindow::onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute)
+{
+#ifndef NV_ARTISTTOOLS
+ SimpleScene::Inst()->GetFurCharacter().updateCurveAttribute(attribute);
+#else
+ CoreLib::Inst()->AppMainWindow_onCurveAttributeChanged(attribute);
+#endif // NV_ARTISTTOOLS
+}
+
+void AppMainWindow::onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute)
+{
+#ifndef NV_ARTISTTOOLS
+ SimpleScene::Inst()->GetFurCharacter().updateColorAttribute(attribute);
+ _graphicalMaterialPanel->updateValues();
+#else
+ CoreLib::Inst()->AppMainWindow_onColorAttributeChanged(attribute);
+#endif // NV_ARTISTTOOLS
+}
+
+void AppMainWindow::onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex)
+{
+#ifndef NV_ARTISTTOOLS
+ SimpleScene::Inst()->GetFurCharacter().reloadColorAttributeTexture(attribute, reloadColorTex, selectedCtrlPntIndex);
+#else
+ CoreLib::Inst()->AppMainWindow_onReloadColorAttributeTexture(attribute, reloadColorTex, selectedCtrlPntIndex);
+#endif // NV_ARTISTTOOLS
+}
+#endif
+
+/*
+ Maya Scheme:
+ ALT + LMB -> Rotate
+ ALT + MMB -> Pan
+ ALT + RMB -> Zoom
+
+ M-wheel -> Zoom
+
+ 3dsMax Scheme:
+ ALT + MMB -> Rotate
+ N/A + MMB -> Pan
+ ALT + SHFT + MMB -> Zoom
+
+ M-wheel -> Zoom
+*/
+
+void AppMainWindow::InitMouseSchemes()
+{
+ ShortCut alt_lmb = qMakePair(Qt::KeyboardModifiers(Qt::AltModifier), Qt::MouseButtons(Qt::LeftButton));
+ ShortCut alt_mmb = qMakePair(Qt::KeyboardModifiers(Qt::AltModifier), Qt::MouseButtons(Qt::MiddleButton));
+ ShortCut alt_rmb = qMakePair(Qt::KeyboardModifiers(Qt::AltModifier), Qt::MouseButtons(Qt::RightButton));
+ ShortCut non_mmb = qMakePair(Qt::KeyboardModifiers(Qt::NoModifier), Qt::MouseButtons(Qt::MiddleButton));
+ ShortCut alt_shft_mmb = qMakePair(Qt::KeyboardModifiers(Qt::AltModifier|Qt::ShiftModifier), Qt::MouseButtons(Qt::MiddleButton));
+
+ _mayaScheme[alt_lmb] = 'R';
+ _mayaScheme[alt_mmb] = 'P';
+ _mayaScheme[alt_rmb] = 'Z';
+
+ _maxScheme[alt_mmb] = 'R';
+ _maxScheme[non_mmb] = 'P';
+ _maxScheme[alt_shft_mmb] = 'Z';
+}
+
+char AppMainWindow::TestMouseScheme( Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons )
+{
+ char op = TestDragCamera(modifiers, buttons);
+
+ if (op != 0)
+ return op;
+
+ if (modifiers == Qt::KeyboardModifier(Qt::ControlModifier))
+ {
+ if (buttons == Qt::MouseButton(Qt::LeftButton))
+ return 'L';
+ else if (buttons == Qt::MouseButton(Qt::MiddleButton))
+ return 'K';
+ }
+
+ if (modifiers == Qt::KeyboardModifier(Qt::ShiftModifier))
+ return 'W';
+
+ return 0;
+}
+
+char AppMainWindow::TestDragCamera( Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons )
+{
+ if(modifiers != Qt::NoModifier && modifiers != Qt::AltModifier) return 0;
+
+ ShortCut input = qMakePair(modifiers, buttons);
+
+ int scheme = _navigationStyle;
+
+ // !! MUST MATCH THE ORDER OF ITEMS IN 'cbNavigationStyle'
+ const int MAYA_SCHEME = 0;
+ const int MAX_SCHEME = 1;
+ if(scheme == MAYA_SCHEME)
+ {
+ auto itr = _mayaScheme.find(input);
+ if(itr != _mayaScheme.end()) return itr.value();
+ }
+ else
+ {
+ auto itr = _maxScheme.find(input);
+ if(itr != _maxScheme.end()) return itr.value();
+ }
+ return 0;
+}
+
+QString AppMainWindow::OpenTextureFile(QString title)
+{
+ QString lastDir = _lastFilePath;
+ QString titleStr = "Open Texture File";
+ if(!title.isEmpty())
+ titleStr = title;
+
+ QString fileName = QFileDialog::getOpenFileName(this, titleStr, lastDir, "Images (*.dds *.png *.bmp *.jpg *.tga)");
+ if(!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ _lastFilePath = fileInfo.absoluteDir().absolutePath();
+ }
+
+ return fileName;
+}
+
+void AppMainWindow::closeEvent (QCloseEvent *event)
+{
+ ViewerOutput::Inst().UnRegisterPrinter(_printer);
+
+ if (1)
+ {
+#if USE_CURVE_EDITOR
+ _curveEditorMainWindow->setParent(NULL);
+#endif
+ event->accept();
+ emit aboutToQuit();
+ return;
+ }
+ if (SimpleScene::Inst()->IsProjectModified() || SimpleScene::Inst()->IsFurModified())
+ {
+ QMessageBox::StandardButton resBtn = QMessageBox::warning(
+ this, tr("Blast Viewer"),
+ tr("Save changes?\n"),
+ QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
+ QMessageBox::Yes);
+ switch (resBtn)
+ {
+ case QMessageBox::Yes:
+#ifndef NV_ARTISTTOOLS
+ if (!menu_saveHair())
+ {
+ event->ignore();
+ return;
+ }
+ if (!menu_saveProject())
+ {
+ event->ignore();
+ return;
+ }
+#else
+ if (!CoreLib::Inst()->AppMainWindow_closeEvent(event))
+ {
+ event->ignore();
+ return;
+ }
+#endif // NV_ARTISTTOOLS
+ break;
+ case QMessageBox::No:
+ break;
+ default:
+ event->ignore();
+ return;
+ }
+ }
+ event->accept();
+ emit aboutToQuit();
+}
+
+void AppMainWindow::updateMainToolbar()
+{
+#ifndef NV_ARTISTTOOLS
+ if (_mainToolbar)
+ _mainToolbar->updateValues();
+#else
+ CoreLib::Inst()->AppMainWindow_updateMainToolbar();
+#endif // NV_ARTISTTOOLS
+}
+
+#ifndef NV_ARTISTTOOLS
+bool AppMainWindow::menu_openProject()
+{
+ QString lastDir = _lastFilePath;
+ QString fileName = QFileDialog::getOpenFileName(this, "Open Hair Project File", lastDir, "Hair Project File (*.furproj)");
+
+ return openProject(fileName);
+}
+
+bool AppMainWindow::menu_saveProject()
+{
+ char message[1024];
+
+ std::string projectFilePath = GlobalSettings::Inst().getAbsoluteFilePath();
+ if (projectFilePath != "")
+ {
+ if (SimpleScene::Inst()->SaveProject(
+ GlobalSettings::Inst().m_projectFileDir.c_str(),
+ GlobalSettings::Inst().m_projectFileName.c_str()
+ ) == false)
+ {
+ QMessageBox messageBox;
+
+ sprintf(message, "Project file %s could not be saved!", (const char*)projectFilePath.c_str());
+ messageBox.critical(0, "Error", message);
+ messageBox.setFixedSize(500, 200);
+ char message[1024];
+ sprintf(message, "Failed to save project file(\"%s\")", (const char*)projectFilePath.c_str());
+ viewer_err(message);
+ return false;
+ }
+
+ sprintf(message, "Project file %s was saved.", (const char*)projectFilePath.c_str());
+
+ /*
+ QMessageBox messageBox;
+ messageBox.information(0, "Info", message);
+ messageBox.setFixedSize(500,200);
+ */
+ viewer_msg(message);
+ return true;
+ }
+ else
+ {
+ return menu_saveProjectAs();
+ }
+ return false;
+}
+
+bool AppMainWindow::menu_saveProjectAs()
+{
+ char message[1024];
+
+ QString lastDir = _lastFilePath;
+ QString fileName = QFileDialog::getSaveFileName(this, "Save Hair Project File", lastDir, "Hair Project File (*.furproj)");
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file = fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->SaveProject(dir, file) == false)
+ {
+ QMessageBox messageBox;
+ sprintf(message, "Project file %s could not be saved!", (const char*)file);
+ messageBox.critical(0, "Error", message);
+ messageBox.setFixedSize(500, 200);
+ return false;
+ }
+
+ sprintf(message, "Project file %s was saved.", (const char*)file);
+
+ /*
+ QMessageBox messageBox;
+ messageBox.information(0, "Info", message);
+ messageBox.setFixedSize(500,200);
+ */
+
+ viewer_msg(message);
+
+ _lastFilePath = fileInfo.absoluteDir().absolutePath();
+ return true;
+ }
+ return false;
+}
+
+bool AppMainWindow::menu_openHair()
+{
+ AppMainWindow& window = AppMainWindow::Inst();
+ QString lastDir = window._lastFilePath;
+ QString fileName = QFileDialog::getOpenFileName(&window, "Open Hair File", lastDir, "Apex Hair File (*.apx;*.apb)");
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file = fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->GetFurCharacter().LoadHairAsset(dir, file) == false)
+ {
+ QMessageBox messageBox;
+ messageBox.critical(0, "Error", "File open error!");
+ messageBox.setFixedSize(500, 200);
+ char message[1024];
+ sprintf(message, "Failed to open hair file(\"%s\")", (const char*)file);
+ viewer_err(message);
+ return false;
+ }
+
+ window._lastFilePath = fileInfo.absoluteDir().absolutePath();
+
+ window.updateUI();
+ return true;
+ }
+
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// event handlers
+bool AppMainWindow::menu_importHair()
+{
+ AppMainWindow& window = AppMainWindow::Inst();
+ QString lastDir = window._lastFilePath;
+ QString fileName = QFileDialog::getOpenFileName(&window, "Import Hair File", lastDir, "Apex Hair File (*.apx;*.apb)");
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file = fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->GetFurCharacter().ImportSelectedHairAsset(dir, file) == false)
+ {
+ QMessageBox messageBox;
+ messageBox.critical(0, "Error", "File open error!");
+ messageBox.setFixedSize(500, 200);
+ char message[1024];
+ sprintf(message, "Failed to import hair file(\"%s\")", (const char*)file);
+ viewer_err(message);
+ return false;
+ }
+
+ window._lastFilePath = fileInfo.absoluteDir().absolutePath();
+
+ window.updateUI();
+ return true;
+ }
+ return false;
+}
+
+
+bool AppMainWindow::menu_saveHair()
+{
+ return SimpleScene::Inst()->GetFurCharacter().SaveHairAsset();
+}
+
+bool AppMainWindow::menu_saveHairAs()
+{
+ AppMainWindow& window = AppMainWindow::Inst();
+ QString lastDir = window._lastFilePath;
+ QString fileName = QFileDialog::getSaveFileName(&window, "Save as", lastDir, "Apex Hair File (*.apx;*.apb)");
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fileInfo(fileName);
+ QByteArray dir = QDir::toNativeSeparators(fileInfo.absoluteDir().absolutePath()).toLocal8Bit();
+ QByteArray file = fileInfo.fileName().toLocal8Bit();
+
+ if (SimpleScene::Inst()->GetFurCharacter().SaveHairAssetAs(dir, file))
+ {
+ window.updateUI();
+ }
+
+ window._lastFilePath = fileInfo.absoluteDir().absolutePath();
+ return true;
+ }
+ return false;
+}
+
+bool AppMainWindow::menu_saveAllHairs()
+{
+ return SimpleScene::Inst()->GetFurCharacter().SaveAllHairs();
+}
+#endif // NV_ARTISTTOOLS \ No newline at end of file
diff --git a/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.h b/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.h
new file mode 100644
index 0000000..4183fc2
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/AppMainWindow.h
@@ -0,0 +1,208 @@
+#ifndef APPMAINWINDOW_H
+#define APPMAINWINDOW_H
+
+#include <QtWidgets/QMainWindow>
+#include <QtWidgets/QProgressDialog>
+
+#include "ui_AppMainWindow.h"
+#include "UIGlobal.h"
+
+class StyleMaterialPanel;
+class AssetControlPanel;
+class PhysicalMaterialPanel;
+class GraphicalMaterialPanel;
+class DisplayFurVisualizersPanel;
+class GeneralAttributePanel;
+class BlastToolbar;
+class LodPanel;
+class DisplayMeshesPanel;
+class DisplayPreferencesPanel;
+class DisplayScenePanel;
+class DisplayLightPanel;
+class DisplayMeshMaterialsPanel;
+
+#if USE_CURVE_EDITOR
+namespace nvidia {
+namespace CurveEditor {
+
+class CurveEditorMainWindow;
+class CurveAttribute;
+class ColorAttribute;
+
+} // namespace CurveEditor
+} // namespace nvidia
+#endif
+
+#if USE_MATERIAL_SET
+class MaterialSetPanel;
+#endif
+
+class D3DWidget;
+class MsgPrinter;
+class AppMainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ AppMainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ ~AppMainWindow();
+
+ CORELIB_EXPORT static AppMainWindow& Inst();
+
+ CORELIB_EXPORT void InitUI();
+ CORELIB_EXPORT void updateUI();
+ CORELIB_EXPORT void updatePluginUI();
+
+ static bool IsExpertMode();
+
+ D3DWidget* GetRenderWidget() {return _d3dWidget;}
+ char TestMouseScheme(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons);
+
+ CORELIB_EXPORT QString OpenTextureFile(QString title = "");
+
+ void setNavigationStyle(int index) { _navigationStyle = index; }
+ int getNavigationStyle() { return _navigationStyle; }
+
+ void closeEvent (QCloseEvent *event);
+
+ CORELIB_EXPORT void startProgress();
+ CORELIB_EXPORT void setProgressMaximum(int m);
+ CORELIB_EXPORT void setProgress(const char* label, int progress = -1);
+ CORELIB_EXPORT void endProgress();
+ CORELIB_EXPORT void quit();
+
+ CORELIB_EXPORT void updateMainToolbar();
+ CORELIB_EXPORT void processDragAndDrop(QString fname);
+ CORELIB_EXPORT bool openProject(QString fileName);
+
+ CORELIB_EXPORT static void setConnectionMode(int);
+
+ DisplayMeshesPanel* GetDisplayMeshesPanel() { return _displayMeshesPanel; }
+ DisplayPreferencesPanel* GetDisplayPreferencesPanel() { return _displayPreferencesPanel; }
+ DisplayScenePanel* GetDisplayScenePanel() { return _displayScenePanel; }
+ DisplayLightPanel* GetDisplayLightPanel() { return _displayLightPanel; }
+
+ void removeBookmark(const QString& name);
+ void renameBookmark(const QString& oldName, const QString& newName);
+
+#if USE_CURVE_EDITOR
+ CORELIB_EXPORT nvidia::CurveEditor::CurveEditorMainWindow* GetCurveEditorMainWindow() { return _curveEditorMainWindow; }
+ CORELIB_EXPORT void UpdateCurveEditor();
+ CORELIB_EXPORT void ShowCurveEditor(int paramId);
+#endif
+
+ inline QString GetFilePath() { return _lastFilePath; }
+signals:
+ void aboutToQuit();
+
+ public slots:
+ CORELIB_EXPORT void menu_clearScene();
+ CORELIB_EXPORT bool menu_openfbx();
+ CORELIB_EXPORT void menu_addBookmark();
+ CORELIB_EXPORT void menu_editBookmarks();
+ CORELIB_EXPORT void menu_bookmarkTriggered(QAction* act);
+ CORELIB_EXPORT void menu_showOutput();
+ CORELIB_EXPORT void menu_showAttributeEditor();
+ CORELIB_EXPORT void menu_about();
+ CORELIB_EXPORT void menu_opendoc();
+ CORELIB_EXPORT void shortcut_frameall();
+ CORELIB_EXPORT void shortcut_hud();
+ CORELIB_EXPORT void shortcut_statistics();
+ CORELIB_EXPORT void shortcut_pause();
+ CORELIB_EXPORT void shortcut_reset();
+ CORELIB_EXPORT void shortcut_escape();
+ CORELIB_EXPORT void shortcut_expert();
+ CORELIB_EXPORT void demo_next();
+ CORELIB_EXPORT void demo_prev();
+ CORELIB_EXPORT void shortcut_output();
+ CORELIB_EXPORT void shortcut_meshmat();
+ CORELIB_EXPORT void shortcut_fitcamera();
+
+#if USE_CURVE_EDITOR
+ CORELIB_EXPORT void menu_showCurveEditor();
+ CORELIB_EXPORT void onCurveAttributeChanged(nvidia::CurveEditor::CurveAttribute* attribute);
+ CORELIB_EXPORT void onColorAttributeChanged(nvidia::CurveEditor::ColorAttribute* attribute);
+ CORELIB_EXPORT void onReloadColorAttributeTexture(nvidia::CurveEditor::ColorAttribute* attribute, bool reloadColorTex, int selectedCtrlPntIndex);
+#endif
+
+private:
+ char TestDragCamera(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons);
+
+public:
+ void InitMenuItems();
+ void InitToolbar();
+ void InitPluginTab();
+ void InitMainTab();
+ void InitMouseSchemes();
+ void InitShortCuts();
+ void updateBookmarkMenu();
+
+ Ui::AppMainWindowClass ui;
+
+ D3DWidget* _d3dWidget;
+ QMenu* _bookmarksMenu;
+
+ DisplayMeshesPanel* _displayMeshesPanel;
+ DisplayPreferencesPanel* _displayPreferencesPanel;
+ DisplayScenePanel* _displayScenePanel;
+ DisplayLightPanel* _displayLightPanel;
+
+
+#if USE_CURVE_EDITOR
+ bool _curveEditorInitizlized;
+ nvidia::CurveEditor::CurveEditorMainWindow* _curveEditorMainWindow;
+#endif
+
+ typedef QPair<Qt::KeyboardModifiers, Qt::MouseButtons> ShortCut;
+ QMap<ShortCut, char> _mayaScheme;
+ QMap<ShortCut, char> _maxScheme;
+ QActionGroup* _bookmarkActionGroup;
+ QAction* _actionAddBookmark;
+ QAction* _actionEditBookmarks;
+
+ QString _lastFilePath;
+
+ int _navigationStyle;
+
+ MsgPrinter* _printer;
+
+ QProgressDialog _progressDialog;
+
+
+ static bool _expertMode;
+
+ CORELIB_EXPORT static int _connectionMode;
+
+#ifndef NV_ARTISTTOOLS
+ BlastToolbar* GetMainToolbar() { return _mainToolbar; }
+ DisplayFurVisualizersPanel* GetFurVisualizersPanel() { return _displayFurVisualizersPanel; }
+
+public slots:
+ bool menu_openProject();
+ bool menu_saveProject();
+ bool menu_saveProjectAs();
+ bool menu_openHair();
+ bool menu_importHair();
+ bool menu_saveHair();
+ bool menu_saveHairAs();
+ bool menu_saveAllHairs();
+
+private:
+ BlastToolbar* _mainToolbar;
+ AssetControlPanel* _assetControlPanel;
+ GeneralAttributePanel* _generalAttributePanel;
+ DisplayFurVisualizersPanel* _displayFurVisualizersPanel;
+ StyleMaterialPanel* _styleMaterialPanel;
+ PhysicalMaterialPanel* _physicalMaterialPanel;
+ GraphicalMaterialPanel* _graphicalMaterialPanel;
+ LodPanel* _lodPanel;
+ DisplayMeshMaterialsPanel* _displayMeshMaterialsPanel;
+#if USE_MATERIAL_SET
+ MaterialSetPanel* _materialSetPanel;
+#endif
+#endif // NV_ARTISTTOOLS
+
+ bool m_bGizmoWithLocal;
+};
+
+#endif // APPMAINWINDOW_H
diff --git a/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.cpp b/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.cpp
new file mode 100644
index 0000000..445067a
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.cpp
@@ -0,0 +1,106 @@
+#include "CameraBookmarksDialog.h"
+#include "SimpleScene.h"
+#include "AppMainWindow.h"
+#include <QtWidgets/QMessageBox>
+
+CameraBookmarksDialog::CameraBookmarksDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ ui.setupUi(this);
+
+ ui.buttonBox->button(QDialogButtonBox::Ok)->setFixedWidth(64);
+ ui.buttonBox->button(QDialogButtonBox::Cancel)->setFixedWidth(64);
+ ui.buttonBox->button(QDialogButtonBox::Ok)->setFixedHeight(23);
+ ui.buttonBox->button(QDialogButtonBox::Cancel)->setFixedHeight(23);
+ setWindowFlags(windowFlags()&~Qt::WindowContextHelpButtonHint);
+
+ QObject::connect(ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept()));
+ QObject::connect(ui.buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject()));
+
+ ui.editBookmarkName->setEnabled(false);
+ ui.btnRename->setEnabled(false);
+ ui.btnDelete->setEnabled(false);
+
+ _fillListWidget();
+}
+
+CameraBookmarksDialog::~CameraBookmarksDialog()
+{
+
+}
+
+void CameraBookmarksDialog::on_listWidgetBookmarks_itemSelectionChanged()
+{
+ if (ui.listWidgetBookmarks->selectedItems().size() == 0)
+ {
+ ui.editBookmarkName->setEnabled(false);
+ ui.btnRename->setEnabled(false);
+ ui.btnDelete->setEnabled(false);
+ }
+ else
+ {
+ QListWidgetItem* item = ui.listWidgetBookmarks->selectedItems().at(0);
+ ui.editBookmarkName->setEnabled(true);
+ ui.btnRename->setEnabled(true);
+ ui.btnDelete->setEnabled(true);
+
+ ui.editBookmarkName->setText(item->text());
+ }
+}
+
+void CameraBookmarksDialog::on_editBookmarkName_textChanged(QString val)
+{
+
+}
+
+void CameraBookmarksDialog::on_btnRename_clicked()
+{
+ if (ui.editBookmarkName->text().isEmpty())
+ {
+ QListWidgetItem* item = ui.listWidgetBookmarks->selectedItems().at(0);
+ ui.editBookmarkName->setText(item->text());
+ }
+ else
+ {
+ if (_isNameConflict(ui.editBookmarkName->text()))
+ {
+ QMessageBox::warning(this, tr("Warning"), tr("The new name is conflict with name of other camera bookmark!"));
+ return;
+ }
+
+ QListWidgetItem* item = ui.listWidgetBookmarks->selectedItems().at(0);
+ SimpleScene::Inst()->renameBookmark(item->text(), ui.editBookmarkName->text());
+ AppMainWindow::Inst().renameBookmark(item->text(), ui.editBookmarkName->text());
+ item->setText(ui.editBookmarkName->text());
+ }
+
+}
+
+void CameraBookmarksDialog::on_btnDelete_clicked()
+{
+ QListWidgetItem* item = ui.listWidgetBookmarks->selectedItems().at(0);
+ SimpleScene::Inst()->removeBookmark(item->text());
+ AppMainWindow::Inst().removeBookmark(item->text());
+ ui.listWidgetBookmarks->takeItem(ui.listWidgetBookmarks->row(item));
+ delete item;
+
+}
+
+void CameraBookmarksDialog::_fillListWidget()
+{
+ QList<QString> bookmarks = SimpleScene::Inst()->getBookmarkNames();
+ ui.listWidgetBookmarks->addItems(bookmarks);
+}
+
+bool CameraBookmarksDialog::_isNameConflict(const QString& name)
+{
+ QList<QString> bookmarks = SimpleScene::Inst()->getBookmarkNames();
+ int bookmarkCount = bookmarks.size();
+ for (int i = 0; i < bookmarkCount; ++i)
+ {
+ if (bookmarks.at(i) == name)
+ return true;
+ }
+
+ return false;
+} \ No newline at end of file
diff --git a/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.h b/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.h
new file mode 100644
index 0000000..13caa42
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/CameraBookmarksDialog.h
@@ -0,0 +1,31 @@
+#ifndef CAMERABOOKMARKSDIALOG_H
+#define CAMERABOOKMARKSDIALOG_H
+
+#include <QtWidgets/QDialog>
+#include "ui_CameraBookmarksDialog.h"
+
+#include "corelib_global.h"
+
+class CameraBookmarksDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ CameraBookmarksDialog(QWidget *parent = 0);
+ ~CameraBookmarksDialog();
+
+private slots:
+CORELIB_EXPORT void on_listWidgetBookmarks_itemSelectionChanged();
+CORELIB_EXPORT void on_editBookmarkName_textChanged(QString val);
+CORELIB_EXPORT void on_btnRename_clicked();
+CORELIB_EXPORT void on_btnDelete_clicked();
+
+private:
+ void _fillListWidget();
+ bool _isNameConflict(const QString& name);
+
+private:
+ Ui::CameraBookmarksDialog ui;
+};
+
+#endif // CAMERABOOKMARKSDIALOG_H
diff --git a/tools/ArtistTools/source/CoreLib/Window/D3DWidget.cpp b/tools/ArtistTools/source/CoreLib/Window/D3DWidget.cpp
new file mode 100644
index 0000000..69be706
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/D3DWidget.cpp
@@ -0,0 +1,151 @@
+#include <QtGui/QResizeEvent>
+#include <QtGui/QMouseEvent>
+#include <QtCore/QTimer>
+#include <QtCore/QMimeData>
+
+#include "D3DWidget.h"
+#include "AppMainWindow.h"
+#include "SimpleScene.h"
+
+D3DWidget::D3DWidget( QWidget* parent )
+ : QWidget(parent, Qt::MSWindowsOwnDC) // Same settings as used in Qt's QGLWidget
+{
+ // same settings as used in QGLWidget to avoid 'white flickering'
+ setAttribute(Qt::WA_PaintOnScreen);
+ setAttribute(Qt::WA_NoSystemBackground);
+
+ // to get rid of 'black flickering'
+ setAttribute(Qt::WA_OpaquePaintEvent, true);
+
+ QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ sizePolicy.setHorizontalStretch(0);
+ sizePolicy.setVerticalStretch(0);
+ setSizePolicy(sizePolicy);
+
+ _appWindow = qobject_cast<AppMainWindow*>(parent);
+ this->setAcceptDrops(true);
+
+ setMouseTracking(true);
+}
+
+void D3DWidget::dragEnterEvent(QDragEnterEvent *e)
+{
+ CoreLib::Inst()->D3DWidget_dragEnterEvent(e);
+ e->acceptProposedAction();
+}
+
+void D3DWidget::dragMoveEvent(QDragMoveEvent *e)
+{
+ CoreLib::Inst()->D3DWidget_dragMoveEvent(e);
+ e->acceptProposedAction();
+}
+
+void D3DWidget::dragLeaveEvent(QDragLeaveEvent *e)
+{
+ CoreLib::Inst()->D3DWidget_dragLeaveEvent(e);
+ //e->acceptProposedAction();
+}
+
+void D3DWidget::dropEvent(QDropEvent *e)
+{
+ CoreLib::Inst()->D3DWidget_dropEvent(e);
+
+ const QMimeData* data = e->mimeData();
+ QString name = data->objectName();
+
+ bool hasUrls = data->hasUrls();
+ if (!hasUrls)
+ return;
+
+ QList<QUrl> urlList = data->urls();
+ QString text;
+ for (int i = 0; i < urlList.size() && i < 32; ++i) {
+ QString url = urlList.at(i).toLocalFile();
+ text += url;
+ }
+
+ e->acceptProposedAction();
+
+ AppMainWindow::Inst().processDragAndDrop(text);
+}
+
+void D3DWidget::paintEvent( QPaintEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_paintEvent(e);
+
+ SimpleScene::Inst()->Draw();
+}
+
+void D3DWidget::Shutdown()
+{
+ SimpleScene::Inst()->Shutdown();
+}
+
+void D3DWidget::Timeout()
+{
+ SimpleScene::Inst()->Timeout();
+}
+
+void D3DWidget::resizeEvent( QResizeEvent* e )
+{
+ int w = e->size().width();
+ int h = e->size().height();
+ // resize calls D3D11RenderWindow::Resize
+ SimpleScene::Inst()->Resize(w,h);
+ // D3DWidget_resizeEvent calls resize in DeviceManager
+ CoreLib::Inst()->D3DWidget_resizeEvent(e);
+}
+
+void D3DWidget::mouseMoveEvent( QMouseEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_mouseMoveEvent(e);
+
+ atcore_float2 pos = gfsdk_makeFloat2(e->x(), e->y());
+ SimpleScene::Inst()->onMouseMove(pos);
+
+ Q_ASSERT(_appWindow != NV_NULL);
+ char mode = _appWindow->TestMouseScheme(e->modifiers(), e->buttons());
+
+ if(mode == 0) return;
+ SimpleScene::Inst()->Drag(mode);
+}
+
+void D3DWidget::wheelEvent(QWheelEvent* e)
+{
+ CoreLib::Inst()->D3DWidget_wheelEvent(e);
+
+ SimpleScene::Inst()->onMouseWheel(e->delta());
+ SimpleScene::Inst()->WheelZoom();
+}
+
+void D3DWidget::mousePressEvent( QMouseEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_mousePressEvent(e);
+
+ atcore_float2 pos = gfsdk_makeFloat2(e->x(), e->y());
+ SimpleScene::Inst()->onMouseDown(pos);
+}
+
+void D3DWidget::mouseReleaseEvent( QMouseEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_mouseReleaseEvent(e);
+
+ atcore_float2 pos = gfsdk_makeFloat2(e->x(), e->y());
+ SimpleScene::Inst()->onMouseUp(pos);
+}
+
+void D3DWidget::keyPressEvent( QKeyEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_keyPressEvent(e);
+}
+
+void D3DWidget::keyReleaseEvent( QKeyEvent* e )
+{
+ CoreLib::Inst()->D3DWidget_keyReleaseEvent(e);
+}
+
+void D3DWidget::contextMenuEvent(QContextMenuEvent *e)
+{
+ CoreLib::Inst()->D3DWidget_contextMenuEvent(e);
+}
+
diff --git a/tools/ArtistTools/source/CoreLib/Window/D3DWidget.h b/tools/ArtistTools/source/CoreLib/Window/D3DWidget.h
new file mode 100644
index 0000000..0de9a1e
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/D3DWidget.h
@@ -0,0 +1,51 @@
+#ifndef D3DWidget_h__
+#define D3DWidget_h__
+
+#include <QtWidgets/QWidget>
+#include "Nv.h"
+
+#include "corelib_global.h"
+
+class AppMainWindow;
+class D3DWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ D3DWidget(QWidget* parent);
+ virtual ~D3DWidget(){}
+
+signals:
+ void DropSignal();
+
+public slots:
+CORELIB_EXPORT void Timeout();
+CORELIB_EXPORT void Shutdown();
+
+protected:
+ // return NULL to ignore system painter
+ virtual QPaintEngine *paintEngine() const { return NV_NULL; }
+
+ // QWidget events
+ virtual void resizeEvent(QResizeEvent* e);
+ virtual void paintEvent(QPaintEvent* e);
+ virtual void mousePressEvent(QMouseEvent* e);
+ virtual void mouseReleaseEvent(QMouseEvent* e);
+ virtual void mouseMoveEvent(QMouseEvent* e);
+ virtual void wheelEvent ( QWheelEvent * e);
+ virtual void keyPressEvent(QKeyEvent* e);
+ virtual void keyReleaseEvent(QKeyEvent* e);
+
+ virtual void dragEnterEvent(QDragEnterEvent *e);
+ virtual void dragMoveEvent(QDragMoveEvent *e);
+ virtual void dragLeaveEvent(QDragLeaveEvent *e);
+ virtual void dropEvent(QDropEvent *e);
+
+ virtual void contextMenuEvent(QContextMenuEvent *e);
+
+private:
+ AppMainWindow* _appWindow;
+};
+
+#endif // D3DWidget_h__
diff --git a/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.cpp b/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.cpp
new file mode 100644
index 0000000..ec267a3
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.cpp
@@ -0,0 +1,263 @@
+#include "AppMainWindow.h"
+#include "DisplayLightPanel.h"
+
+#include "Light.h"
+#include "GlobalSettings.h"
+
+#include <QtWidgets/QColorDialog>
+#include <QtCore/QFileInfo>
+
+DisplayLightPanel::DisplayLightPanel(QWidget* parent)
+ :
+ QWidget(parent)
+{
+ ui.setupUi(this);
+ _isUpdatingUI = false;
+
+ ConfigSpinBox<SlideSpinBoxF>(ui.spinLightDistance, 0.0, 1000.0, 0.1);
+ ConfigSpinBox<SlideSpinBoxF>(ui.spinLightIntensity, 0.0, 5.0, 0.01);
+
+ ui.btnLightColorTex->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+ ui.btnLightColorTex->setIconSize(QSize(12,12));
+ ui.btnLightColorTexReload->setIcon(QIcon(":/AppMainWindow/images/Refresh_icon.png"));
+ ui.btnLightColorTexClear->setIcon(QIcon(":/AppMainWindow/images/Remove_icon.png"));
+
+ connect(ui.listSelectedLight, SIGNAL(itemSelectionChanged()), this, SLOT(onListSelectionChanged()));
+}
+
+void DisplayLightPanel::onListSelectionChanged()
+{
+ if (_isUpdatingUI)
+ return;
+
+ int numSelected = ui.listSelectedLight->selectedItems().count();
+
+ // change selection only when there is something selected
+ if (numSelected > 0)
+ {
+ int numItems = ui.listSelectedLight->count();
+ {
+ for (int i = 0; i < numItems; i++)
+ {
+ bool selected = ui.listSelectedLight->item(i)->isSelected();
+ Light::GetLight(i)->m_selected = selected;
+ }
+ }
+ }
+
+ updateUI();
+}
+
+void DisplayLightPanel::on_cbShadowMapResolution_currentIndexChanged( int index )
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->SetShadowMapResolution(index);
+ }
+}
+
+void DisplayLightPanel::on_btnLightUseShadow_stateChanged(int state)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->m_useShadows = state;
+ }
+}
+
+void DisplayLightPanel::on_btnVisualizeLight_stateChanged(int state)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->m_visualize = state;
+ }
+}
+
+void DisplayLightPanel::on_btnLightEnable_stateChanged(int state)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->m_enable = state;
+ }
+}
+
+void DisplayLightPanel::on_btnLinkLightEnable_stateChanged(int state)
+{
+ Light::SetLinkLightOption(state != 0 ? true : false);
+}
+
+void DisplayLightPanel::on_spinLightDistance_valueChanged(double v)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->SetDistance(v);
+ }
+}
+
+void DisplayLightPanel::on_spinLightIntensity_valueChanged(double v)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->m_intensity = v;
+ }
+}
+
+void DisplayLightPanel::on_btnVisualizeShadowMap_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_visualizeShadowMap = state;
+}
+
+void DisplayLightPanel::setButtonColor(QPushButton *button, float r, float g, float b)
+{
+ QColor specColor;
+ specColor.setRgbF(r,g,b);
+ QString specBtnStyle = QString("background-color: rgb(%1,%2,%3);")
+ .arg(specColor.red())
+ .arg(specColor.green())
+ .arg(specColor.blue());
+ button->setStyleSheet(specBtnStyle);
+}
+
+
+static bool getNewColor(atcore_float3& color)
+{
+ QColor currentColor;
+ currentColor.setRgbF(color.x, color.y, color.z);
+
+ QColor newColor = QColorDialog::getColor(currentColor, NV_NULL);
+ if(newColor.isValid())
+ {
+ qreal r,g,b;
+ newColor.getRgbF(&r, &g, &b);
+
+ color.x = r;
+ color.y = g;
+ color.z = b;
+ return true;
+ }
+
+ return false;
+}
+
+void DisplayLightPanel::on_btnLightColor_clicked()
+{
+ Light* pLight = Light::GetFirstSelectedLight();
+
+ atcore_float3 color = pLight->m_color;
+
+ if (getNewColor(color))
+ setButtonColor(ui.btnLightColor, color.x, color.y, color.z);
+
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight || !pLight->m_selected)
+ continue;
+
+ pLight->m_color = color;
+ }
+}
+
+inline void SetTextureIcon(QPushButton* pButton, bool enabled)
+{
+ if (enabled)
+ pButton->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+ else
+ pButton->setIcon(QIcon(":/AppMainWindow/images/TextureIsUsed_icon.png"));
+}
+
+void DisplayLightPanel::on_btnLightColorTex_clicked()
+{
+ QString texName = AppMainWindow::Inst().OpenTextureFile();
+ QFileInfo fileInfo(texName);
+ QByteArray ba = fileInfo.absoluteFilePath().toLocal8Bit();
+
+ if (Light::SetEnvTextureFromFilePath((const char*)ba))
+ SetTextureIcon(ui.btnLightColorTex, Light::GetEnvTextureFilePath().empty());
+}
+
+void DisplayLightPanel::on_btnLightColorTexReload_clicked()
+{
+ std::string path = Light::GetEnvTextureFilePath();
+ if (Light::SetEnvTextureFromFilePath(path.c_str()))
+ SetTextureIcon(ui.btnLightColorTex, Light::GetEnvTextureFilePath().empty());
+}
+
+void DisplayLightPanel::on_btnLightColorTexClear_clicked()
+{
+ Light::SetEnvTextureFromFilePath(nullptr);
+ SetTextureIcon(ui.btnLightColorTex, Light::GetEnvTextureFilePath().empty());
+}
+
+void DisplayLightPanel::updateUI()
+{
+ Light* pLight = Light::GetFirstSelectedLight();
+ if (!pLight)
+ return;
+
+ atcore_float3& color = pLight->m_color;
+ setButtonColor(ui.btnLightColor, color.x, color.y, color.z);
+
+ ui.btnVisualizeLight->setChecked(pLight->m_visualize);
+
+ ui.spinLightDistance->setValue(pLight->GetDistance());
+ ui.spinLightIntensity->setValue(pLight->m_intensity);
+
+ ui.btnLightUseShadow->setChecked(pLight->m_useShadows);
+ ui.btnLightEnable->setChecked(pLight->m_enable);
+
+ ui.btnVisualizeShadowMap->setChecked(GlobalSettings::Inst().m_visualizeShadowMap);
+
+ ui.cbShadowMapResolution->setCurrentIndex(pLight->m_shadowMapResolutionIndex);
+
+ ui.btnLinkLightEnable->setChecked(Light::GetLinkLightOption());
+
+ SetTextureIcon(ui.btnLightColorTex, Light::GetEnvTextureFilePath().empty());
+}
+
+void DisplayLightPanel::updateValues()
+{
+ _isUpdatingUI = true;
+
+ ui.listSelectedLight->clear();
+ for (int i = 0; i < 4; i++)
+ {
+ Light* pLight = Light::GetLight(i);
+ if (!pLight)
+ continue;
+
+ const char* lightName = pLight->m_name.c_str();
+ bool selected = pLight->m_selected;
+
+ ui.listSelectedLight->addItem(lightName);
+ ui.listSelectedLight->item(i)->setSelected(selected);
+ }
+ ui.listSelectedLight->setSelectionMode(QAbstractItemView::ExtendedSelection);
+
+ updateUI();
+
+ _isUpdatingUI = false;
+}
diff --git a/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.h b/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.h
new file mode 100644
index 0000000..e22eae4
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/DisplayLightPanel.h
@@ -0,0 +1,47 @@
+#ifndef DisplayLightPanel_h__
+#define DisplayLightPanel_h__
+
+#include <QtWidgets/QWidget>
+#include "ui_DisplayLightPanel.h"
+
+#include "corelib_global.h"
+
+class DisplayLightPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DisplayLightPanel(QWidget* parent);
+
+ public:
+ CORELIB_EXPORT void updateValues();
+
+ public slots:
+ CORELIB_EXPORT void onListSelectionChanged();
+
+ CORELIB_EXPORT void on_spinLightDistance_valueChanged(double v);
+ CORELIB_EXPORT void on_spinLightIntensity_valueChanged(double v);
+
+ CORELIB_EXPORT void on_btnLightUseShadow_stateChanged(int state);
+ CORELIB_EXPORT void on_btnVisualizeLight_stateChanged(int state);
+ CORELIB_EXPORT void on_btnLightEnable_stateChanged(int state);
+ CORELIB_EXPORT void on_btnLinkLightEnable_stateChanged(int state);
+
+ CORELIB_EXPORT void on_btnLightColor_clicked();
+ CORELIB_EXPORT void on_btnLightColorTex_clicked();
+ CORELIB_EXPORT void on_btnLightColorTexReload_clicked();
+ CORELIB_EXPORT void on_btnLightColorTexClear_clicked();
+
+ CORELIB_EXPORT void on_btnVisualizeShadowMap_stateChanged(int state);
+
+ CORELIB_EXPORT void on_cbShadowMapResolution_currentIndexChanged(int index);
+
+private:
+ Ui::DisplayLightPanel ui;
+ bool _isUpdatingUI;
+ void setButtonColor(QPushButton *button, float r, float g, float b);
+
+ void updateUI();
+};
+
+#endif
diff --git a/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.cpp b/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.cpp
new file mode 100644
index 0000000..67ca141
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.cpp
@@ -0,0 +1,177 @@
+#include "DisplayMeshesPanel.h"
+
+#include <QtWidgets/QGridLayout>
+#include <QtWidgets/QHBoxLayout>
+#include <QtWidgets/QPushButton>
+
+#include "AppMainWindow.h"
+
+#include "SimpleScene.h"
+
+#ifndef NV_ARTISTTOOLS
+#include "FurCharacter.h"
+#else
+#endif // NV_ARTISTTOOLS
+
+//////////////////////////////////////////////////////////////////////////
+// DisplayMeshItem
+
+StateViewItem::StateViewItem( QWidget* parent, unsigned int id, MeshViewState view /*= VS_VISIABLE*/ )
+ : _id(id)
+{
+ static QIcon iconVisible(":/AppMainWindow/images/visibilityToggle_visible.png");
+ static QIcon iconNotVisible(":/AppMainWindow/images/visibilityToggle_notVisible.png");
+
+ _parent = qobject_cast<DisplayMeshesPanel*>(parent);
+
+ _layout = new QHBoxLayout(this);
+ _layout->setObjectName(QString::fromUtf8("boxLayout"));
+ _layout->setMargin(0);
+
+ this->setLayout(_layout);
+
+ _btn = new QPushButton(this);
+
+ _btn->setObjectName(QString::fromUtf8("btnToggleView"));
+ QSizePolicy sizePolicy1(QSizePolicy::Ignored, QSizePolicy::Fixed);
+ sizePolicy1.setHorizontalStretch(0);
+ sizePolicy1.setVerticalStretch(0);
+ sizePolicy1.setHeightForWidth(_btn->sizePolicy().hasHeightForWidth());
+ _btn->setSizePolicy(sizePolicy1);
+ _btn->setMinimumSize(QSize(16, 16));
+ _btn->setMaximumSize(QSize(16, 16));
+ _btn->setAutoFillBackground(false);
+ _btn->setCheckable(true);
+ _btn->setChecked(view == VS_VISIABLE);
+ _btn->setIcon( (view == VS_VISIABLE) ? iconVisible : iconNotVisible);
+
+ _layout->addWidget(_btn);
+
+ _spacer = new QSpacerItem(20, 40, QSizePolicy::Expanding, QSizePolicy::Ignored);
+ _layout->addItem(_spacer);
+
+ QMetaObject::connectSlotsByName(this);
+}
+
+void StateViewItem::on_btnToggleView_clicked()
+{
+ static QIcon iconVisible(":/AppMainWindow/images/visibilityToggle_visible.png");
+ static QIcon iconNotVisible(":/AppMainWindow/images/visibilityToggle_notVisible.png");
+
+ bool bVis = _btn->isChecked();
+ _btn->setIcon(bVis ? iconVisible : iconNotVisible);
+
+ _parent->EmitToggleSignal(_id, bVis);
+
+ qDebug("%s", __FUNCTION__);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+DisplayMeshesPanel::DisplayMeshesPanel( QWidget* parent )
+ :QFrame(parent)
+{
+ _layout = new QGridLayout(this);
+ _layout->setObjectName(QString::fromUtf8("gridLayout"));
+
+ this->setLayout(_layout);
+
+ //QString styleSheet =
+ // "QPushButton#btnToggleView:checked {border:2px solid gray; background:rgb(118,180,0);} \n" \
+ // "QPushButton#btnToggleView:pressed {border:2px solid gray; background:rgb(118,180,0);}";
+ //setStyleSheet(styleSheet);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void DisplayMeshesPanel::updateValues()
+{
+ ClearItems();
+
+#ifndef NV_ARTISTTOOLS
+ FurCharacter& character = SimpleScene::Inst()->GetFurCharacter();
+ int nMesh = character.GetMeshCount();
+ for (int i = 0; i < nMesh; ++i)
+ {
+ bool used = character.GetMeshUsed(i);
+ if (!used)
+ continue;
+
+ const char* name = character.GetMeshName(i);
+ bool visible = character.GetMeshVisible(i);
+
+ StateViewItem::MeshViewState visState = visible ? StateViewItem::VS_VISIABLE : StateViewItem::VS_INVISIBLE;
+
+ AddMeshItem(QString(name), i, visState);
+ }
+#else
+ CoreLib::Inst()->DisplayMeshesPanel_updateValues();
+#endif // NV_ARTISTTOOLS
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void DisplayMeshesPanel::AddMeshItem( QString name, unsigned int id, StateViewItem::MeshViewState view )
+{
+ StateViewItem* item;
+ item = new StateViewItem(this, id, view);
+
+ QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ sizePolicy1.setHorizontalStretch(0);
+ sizePolicy1.setVerticalStretch(0);
+
+ QLabel* label = new QLabel(name, this);
+ label->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+ label->setSizePolicy(sizePolicy1);
+
+ int row = _items.size();
+ _layout->addWidget(label, row, 0, 1, 1);
+
+ _layout->addWidget(item, row, 1, 1, 1);
+
+ Q_ASSERT(_items.find(id) == _items.end());
+
+ ItemUI ui;
+ ui.label = label;
+ ui.viewItem = item;
+ _items[id] = ui;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void DisplayMeshesPanel::EmitToggleSignal( unsigned int id, bool visible )
+{
+ emit MeshViewSignal(id, visible);
+
+#ifndef NV_ARTISTTOOLS
+ FurCharacter& character = SimpleScene::Inst()->GetFurCharacter();
+ character.SetMeshVisible(id, visible);
+#else
+ CoreLib::Inst()->DisplayMeshesPanel_EmitToggleSignal(id, visible);
+#endif // NV_ARTISTTOOLS
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void DisplayMeshesPanel::RemoveMeshItem( unsigned int id )
+{
+ if(_items.find(id) != _items.end())
+ {
+ ItemUI ui = _items[id];
+ delete ui.label;
+ delete ui.viewItem;
+ _items.remove(id);
+ }
+ else
+ {
+ Q_ASSERT("Mesh item doesn't exist!!");
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void DisplayMeshesPanel::ClearItems()
+{
+ Q_FOREACH(ItemUI ui, _items)
+ {
+ delete ui.label;
+ delete ui.viewItem;
+ }
+
+ _items.clear();
+}
diff --git a/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.h b/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.h
new file mode 100644
index 0000000..ecc5b49
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/DisplayMeshesPanel.h
@@ -0,0 +1,80 @@
+#ifndef DisplayMeshesPanel_h__
+#define DisplayMeshesPanel_h__
+
+#include <QtWidgets/QFrame>
+#include <QtCore/QMap>
+#ifndef NV_ARTISTTOOLS
+#include "ui_LodPanel.h"
+#else
+#include <QtWidgets/QLabel>
+#endif // NV_ARTISTTOOLS
+
+#include "corelib_global.h"
+
+class QPushButton;
+class QGridLayout;
+class QHBoxLayout;
+class QSpacerItem;
+
+class DisplayMeshesPanel;
+class StateViewItem : public QWidget
+{
+ Q_OBJECT
+
+public:
+ enum MeshViewState
+ {
+ VS_INVISIBLE = 0,
+ VS_VISIABLE = 1,
+ };
+
+ StateViewItem(QWidget* parent, unsigned int id, MeshViewState view = VS_VISIABLE);
+
+ public slots:
+ CORELIB_EXPORT void on_btnToggleView_clicked();
+
+private:
+ unsigned int _id;
+
+ QHBoxLayout* _layout;
+ QPushButton* _btn;
+ QSpacerItem* _spacer;
+
+ DisplayMeshesPanel* _parent;
+};
+
+class DisplayMeshesPanel : public QFrame
+{
+ Q_OBJECT
+
+public:
+ DisplayMeshesPanel(QWidget* parent);
+
+ void updateValues();
+
+ // client code should make sure the 'id' is unique!
+ CORELIB_EXPORT void AddMeshItem(QString name, unsigned int id, StateViewItem::MeshViewState view = StateViewItem::VS_VISIABLE);
+ CORELIB_EXPORT void RemoveMeshItem(unsigned int id);
+ CORELIB_EXPORT void ClearItems();
+
+signals:
+ void MeshViewSignal(unsigned int id, bool visible);
+
+protected:
+ virtual void EmitToggleSignal(unsigned int id, bool visible);
+
+private:
+ QGridLayout* _layout;
+
+ struct ItemUI
+ {
+ StateViewItem* viewItem;
+ QLabel* label;
+ };
+
+ QMap<unsigned int, ItemUI> _items;
+
+ friend class StateViewItem;
+};
+
+#endif // GraphicalMaterialPanel_h__
diff --git a/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.cpp b/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.cpp
new file mode 100644
index 0000000..fe4b808
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.cpp
@@ -0,0 +1,906 @@
+#include "DisplayPreferencesPanel.h"
+
+#include "AppMainWindow.h"
+
+#include "SimpleScene.h"
+#include "GlobalSettings.h"
+#include <QtWidgets/QInputDialog>
+#include <QtWidgets/QMessageBox>
+#include <QtWidgets/QFileDialog>
+
+#include "PlaylistParams.h"
+//#include <Nv/Blast/NvHairCommon.h>
+#include "NvParameterized.h"
+#include "XmlSerializer.h"
+#include "NsFileBuffer.h"
+#include "NvTraits.h"
+#include "NsMemoryBuffer.h"
+#include "ViewerOutput.h"
+#include "Settings.h"
+
+#include "Gamepad.h"
+
+const QString sPlaylistExt = "plist";
+bool bRefreshingComboBox = false;
+
+DisplayPreferencesPanel::DisplayPreferencesPanel(QWidget* parent)
+ :
+ QWidget(parent)
+ , idxCurrentPlaylist(-1)
+ , idxCurrentProj(-1)
+ , playlistProjectsDirty(false)
+{
+ ui.setupUi(this);
+
+ ui.btnBackgroundTex->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+ ui.btnBackgroundTex->setIconSize(QSize(12,12));
+ ui.btnBackgroundTexClear->setIcon(QIcon(":/AppMainWindow/images/Remove_icon.png"));
+
+ ui.btnPlaylistsRename->setIcon(QIcon(":/AppMainWindow/images/EditWrench.png"));
+ ui.btnPlaylistsAdd->setIcon(QIcon(":/AppMainWindow/images/Add.png"));
+ ui.btnPlaylistsReload->setIcon(QIcon(":/AppMainWindow/images/refreshReload.png"));
+ ui.btnPlaylistsRemove->setIcon(QIcon(":/AppMainWindow/images/Remove_icon.png"));
+
+ ui.btnPlaylistAddProj->setIcon(QIcon(":/AppMainWindow/images/Add.png"));
+ ui.btnPlaylistRemoveProj->setIcon(QIcon(":/AppMainWindow/images/Remove_icon.png"));
+ ui.btnPlaylistProjGoUp->setIcon(QIcon(":/AppMainWindow/images/Up.png"));
+ ui.btnPlaylistProjGoDown->setIcon(QIcon(":/AppMainWindow/images/Down.png"));
+
+ ui.btnPlaylistsPlay->setIcon(QIcon(":/AppMainWindow/images/playlist.png"));
+
+ //QObject::connect(ui.listWidgetPlaylist, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(playlistDoubleClicked(QListWidgetItem*)));
+
+ ConfigSpinBox<SlideSpinBoxF>(ui.spinCameraFOV, 5.0, 180.0, 1.0);
+}
+
+DisplayPreferencesPanel::~DisplayPreferencesPanel()
+{
+}
+
+void DisplayPreferencesPanel::on_spinRenderPlayRateFPS_valueChanged(double v)
+{
+ GlobalSettings::Inst().setRenderFps((float)v);
+}
+
+void DisplayPreferencesPanel::on_spinSimulationRateFPS_valueChanged(double v)
+{
+ GlobalSettings::Inst().setSimulationFps((float)v);
+}
+
+void DisplayPreferencesPanel::on_spinCameraFOV_valueChanged(double v)
+{
+ GlobalSettings::Inst().m_fovAngle = v;
+}
+
+void DisplayPreferencesPanel::on_cbAntialiasing_currentIndexChanged( int index )
+{
+ GlobalSettings::Inst().m_msaaOption = index;
+}
+
+void DisplayPreferencesPanel::on_cbUpAxis_currentIndexChanged( int index )
+{
+ switch (index)
+ {
+ case 0: // y up
+ SimpleScene::Inst()->ResetUpDir(false);
+ break;
+ case 1: // z up
+ SimpleScene::Inst()->ResetUpDir(true);
+ break;
+ }
+ SimpleScene::Inst()->SetProjectModified(true);
+}
+
+void DisplayPreferencesPanel::on_cbHandedness_currentIndexChanged( int index )
+{
+ switch (index)
+ {
+ case 0: // rhs
+ SimpleScene::Inst()->ResetLhs(false);
+ break;
+ case 1: // lhs
+ SimpleScene::Inst()->ResetLhs(true);
+ break;
+ }
+ SimpleScene::Inst()->SetProjectModified(true);
+}
+
+void DisplayPreferencesPanel::on_cbSceneUnit_currentIndexChanged( int index )
+{
+ GlobalSettings::Inst().m_sceneUnitIndex = index;
+}
+
+void DisplayPreferencesPanel::on_cbNavigationStyle_currentIndexChanged( int index )
+{
+ AppMainWindow::Inst().setNavigationStyle(index);
+}
+
+void DisplayPreferencesPanel::on_btnBackgroundTex_clicked()
+{
+ if (SimpleScene::Inst()->LoadBackgroundTextureFile())
+ ui.btnBackgroundTex->setIcon(QIcon(":/AppMainWindow/images/TextureIsUsed_icon.png"));
+ else
+ ui.btnBackgroundTex->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+
+ updateValues();
+ SimpleScene::Inst()->SetProjectModified(true);
+}
+
+void DisplayPreferencesPanel::on_btnBackgroundTexClear_clicked()
+{
+ SimpleScene::Inst()->ClearBackgroundTexture();
+ ui.btnBackgroundTex->setIcon(QIcon(":/AppMainWindow/images/TextureEnabled_icon.png"));
+ updateValues();
+}
+
+void DisplayPreferencesPanel::updateValues()
+{
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ ui.spinRenderPlayRateFPS->setValue(globalSettings.m_renderFps);
+ ui.spinSimulationRateFPS->setValue(globalSettings.m_simulationFps);
+ ui.cbUpAxis->setCurrentIndex(globalSettings.m_zup);
+ ui.cbHandedness->setCurrentIndex(globalSettings.m_lhs);
+ ui.spinCameraFOV->setValue(globalSettings.m_fovAngle);
+ ui.cbSceneUnit->setCurrentIndex(globalSettings.m_sceneUnitIndex);
+ ui.cbNavigationStyle->setCurrentIndex(AppMainWindow::Inst().getNavigationStyle());
+ ui.cbAntialiasing->setCurrentIndex(globalSettings.m_msaaOption);
+
+ savePlaylistProjects();
+ reloadComboxBoxPlaylists();
+
+ //// sync playlist to gamepad
+ //static bool bOnce = true;
+ //if (bOnce)
+ //{
+ // bOnce = false;
+ // assignPlayPlaylistToGamepad(0);
+ //}
+}
+
+void DisplayPreferencesPanel::reloadComboxBoxPlaylists()
+{
+ playlistsLoader.loadPlaylistsFromMediaPath();
+ // set playlist combo box
+ //idxCurrentPlaylist = ui.cbPlaylists->currentIndex();
+ bRefreshingComboBox = true;
+ ui.cbPlaylists->clear();
+ int count = playlistsLoader.playlists.size();
+ for (int i = 0; i < count; ++i)
+ {
+ QFileInfo& fi = playlistsLoader.playlists[i];
+ std::string fn = fi.fileName().toUtf8().data();
+ ui.cbPlaylists->addItem(fi.fileName());
+ }
+ bRefreshingComboBox = false;
+ if (idxCurrentPlaylist > count || idxCurrentPlaylist < 0)
+ idxCurrentPlaylist = 0;
+
+ ui.cbPlaylists->setCurrentIndex(idxCurrentPlaylist);
+
+ // refresh project list
+ reloadListboxPorjectsFromPlayist();
+}
+
+void DisplayPreferencesPanel::runDemoCommandline()
+{
+ // run demos if command line asks
+ static bool once = true;
+ if (once)
+ {
+ once = false;
+ std::string demoPlaylist = AppSettings::Inst().GetOptionValue("User/FurDemoPlaylist")->Value.String;
+ if (demoPlaylist.size() > 1)
+ {
+ QString demoList = QString(demoPlaylist.c_str()).toUpper();
+ int count = playlistsLoader.playlists.size();
+ for (int i = 0; i < count; ++i)
+ {
+ QFileInfo& fi = playlistsLoader.playlists[i];
+ QString fname = fi.fileName().toUpper();
+ if (fname == demoList)
+ {
+ idxCurrentPlaylist = i;
+ ui.cbPlaylists->setCurrentIndex(idxCurrentPlaylist);
+ playPlaylist(idxCurrentPlaylist);
+ return;
+ }
+ }
+ viewer_msg(QString("Cannot find playlist, " + demoList).toUtf8().data());
+ }
+ }
+}
+
+void DisplayPreferencesPanel::reloadListboxPorjectsFromPlayist()
+{
+ int count = playlistsLoader.getProjectsInPlaylist(idxCurrentPlaylist, playlistProjects);
+ refreshListboxPorjects();
+}
+
+void DisplayPreferencesPanel::savePlaylistProjects()
+{
+ if (playlistProjectsDirty)
+ {
+ playlistsLoader.saveProjectsInPlaylist(idxCurrentPlaylist, playlistProjects);
+ playlistProjectsDirty = false;
+ }
+}
+
+void DisplayPreferencesPanel::refreshListboxPorjects()
+{
+ int count = playlistProjects.size();
+ ui.listWidgetPlaylist->clear();
+ ui.listWidgetPlaylist->setSortingEnabled(false);
+ ui.listWidgetPlaylist->setSelectionMode(QAbstractItemView::SingleSelection);
+ QStringList tips;
+ for (int i = 0; i < count; ++i)
+ {
+ QString fullName = playlistsLoader.convertToAbsoluteFilePath(playlistProjects[i]);
+ QFileInfo fi(fullName);
+ tips.append(fi.absoluteFilePath());
+ std::string tmp = fi.absoluteFilePath().toUtf8().data();
+ ui.listWidgetPlaylist->addItem(fi.fileName());
+ }
+ ui.listWidgetPlaylist->setTips(tips);
+ if (idxCurrentProj > count || idxCurrentProj < 0)
+ {
+ idxCurrentProj = 0;
+ }
+ ui.listWidgetPlaylist->setCurrentRow(idxCurrentProj);
+}
+
+void DisplayPreferencesPanel::SelectPlayList(QString& name)
+{
+ QString newName = name.toUpper();
+ int count = playlistsLoader.playlists.size();
+ for (int i = 0; i < count; ++i)
+ {
+ QFileInfo& fi = playlistsLoader.playlists[i];
+ if (fi.baseName().toUpper() == newName)
+ {
+ ui.cbPlaylists->setCurrentIndex(i);
+ break;
+ }
+ }
+}
+
+void DisplayPreferencesPanel::on_cbPlaylists_currentIndexChanged(int index)
+{
+ savePlaylistProjects();
+ if (!bRefreshingComboBox)
+ {
+ idxCurrentPlaylist = ui.cbPlaylists->currentIndex();
+ reloadListboxPorjectsFromPlayist();
+ }
+}
+
+void DisplayPreferencesPanel::SelectProject(QString& name)
+{
+ QString newName = name.toUpper();
+ std::string strNew = newName.toUtf8().data();
+ int count = playlistProjects.size();
+ for (int i = 0; i < count; ++i)
+ {
+ QString& str = playlistProjects[i];
+ //QFileInfo fi(str);
+ //std::string stmp = fi.absoluteFilePath().toUtf8().data();
+ //if (fi.absoluteFilePath().toUpper() == newName)
+ if (str.toUpper() == newName)
+ {
+ ui.listWidgetPlaylist->setCurrentRow(i);
+ break;
+ }
+ }
+}
+
+void DisplayPreferencesPanel::on_listWidgetPlaylist_itemSelectionChanged()
+{
+ idxCurrentProj = ui.listWidgetPlaylist->currentRow();
+}
+
+void DisplayPreferencesPanel::on_listWidgetPlaylist_itemDoubleClicked(QListWidgetItem* pItem)
+{
+ idxCurrentProj = ui.listWidgetPlaylist->currentRow();
+ if (idxCurrentProj < 0)
+ return;
+ QString fn = playlistProjects[idxCurrentProj];
+ QString fullname = PlaylistsLoader::convertToAbsoluteFilePath(fn);
+ AppMainWindow::Inst().openProject(fullname);
+ char msg[1024];
+ sprintf(msg, "Blast Viewer - %s", fullname.toUtf8().data());
+ AppMainWindow::Inst().setWindowTitle(msg);
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistsRename_clicked()
+{
+ idxCurrentPlaylist = ui.cbPlaylists->currentIndex();
+ if (idxCurrentPlaylist < 0)
+ return;
+
+ QFileInfo& fi = playlistsLoader.playlists[idxCurrentPlaylist];
+ bool isOK = false;
+ QString newBaseName = QInputDialog::getText(NULL, "Rename Playlist - " + fi.fileName(),
+ "Input a new name for the playlist, " + fi.fileName(), QLineEdit::Normal,
+ fi.baseName(), &isOK);
+ if (isOK)
+ {
+ bool ok = playlistsLoader.rename(idxCurrentPlaylist, newBaseName);
+ if (ok)
+ {
+ reloadComboxBoxPlaylists();
+ SelectPlayList(newBaseName);
+ }
+ else
+ {
+ QMessageBox::warning(this, "Fail to rename a playlist",
+ "Fail to rename a playlist. The failure could relate to name duplication or hardware failure.",
+ QMessageBox::Close);
+ }
+ }
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistsAdd_clicked()
+{
+ savePlaylistProjects();
+
+ bool isOK = false;
+ QString sInput = QInputDialog::getText(NULL, "Create New Playlist", "Input a name for the new playlist.", QLineEdit::Normal, "", &isOK);
+ if (isOK)
+ {
+ QString newName = sInput.trimmed();
+ bool ok = playlistsLoader.add(newName);
+ if (ok)
+ {
+ reloadComboxBoxPlaylists();
+ // select the new one
+ SelectPlayList(newName);
+ }
+ else
+ {
+ QMessageBox::warning(this, "Fail to add new playlist",
+ "Fail to add new playlist. The failure could relate to name duplication or hardware failure.",
+ QMessageBox::Close);
+ }
+ }
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistsReload_clicked()
+{
+ savePlaylistProjects();
+ reloadComboxBoxPlaylists();
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistsRemove_clicked()
+{
+ savePlaylistProjects();
+ idxCurrentPlaylist = ui.cbPlaylists->currentIndex();
+ if (idxCurrentPlaylist < 0)
+ return;
+
+ bool ok = playlistsLoader.remove(idxCurrentPlaylist);
+ if (ok)
+ {
+ reloadComboxBoxPlaylists();
+ }
+ else
+ {
+ QMessageBox::warning(this, "Fail to remove a playlist",
+ "Fail to remove a playlist. The failure could relate to hardware.",
+ QMessageBox::Close);
+ }
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistAddProj_clicked()
+{
+ static QString lastPath;
+ if (lastPath.size() < 1)
+ {
+ lastPath = PlaylistsLoader::mediaPath;
+ }
+ QString fileNameInput = QFileDialog::getOpenFileName(this, "Open Hair Project File", lastPath, "Hair Project File (*.furproj)");
+ if (!QFile::exists(fileNameInput))
+ return;
+ std::string tmp = fileNameInput.toUtf8().data();
+ QString fileName = PlaylistsLoader::convertToSaveingFilePath(fileNameInput);
+ if (fileName.size() < 1)
+ {
+ return;
+ }
+ lastPath = QFileInfo(fileNameInput).absolutePath();
+ std::string tmp2 = fileName.toUtf8().data();
+ playlistProjects.append(fileName);
+ refreshListboxPorjects();
+ //QFileInfo fi(fileName);
+ SelectProject(fileName);// fi.absoluteFilePath());
+ playlistProjectsDirty = true;
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistProjGoUp_clicked()
+{
+ idxCurrentProj = ui.listWidgetPlaylist->currentRow();
+ if (idxCurrentProj <= 0)
+ return;
+
+ QString tmp = playlistProjects[idxCurrentProj];
+ playlistProjects[idxCurrentProj] = playlistProjects[idxCurrentProj - 1];
+ playlistProjects[idxCurrentProj - 1] = tmp;
+
+ refreshListboxPorjects();
+ SelectProject(tmp);
+
+ playlistProjectsDirty = true;
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistProjGoDown_clicked()
+{
+ int count = playlistProjects.size();
+ idxCurrentProj = ui.listWidgetPlaylist->currentRow();
+ if (idxCurrentProj < 0 || idxCurrentProj>= count -1)
+ return;
+
+ QString tmp = playlistProjects[idxCurrentProj];
+ playlistProjects[idxCurrentProj] = playlistProjects[idxCurrentProj + 1];
+ playlistProjects[idxCurrentProj + 1] = tmp;
+
+ refreshListboxPorjects();
+ SelectProject(tmp);
+
+ playlistProjectsDirty = true;
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistRemoveProj_clicked()
+{
+ int count = playlistProjects.size();
+ idxCurrentProj = ui.listWidgetPlaylist->currentRow();
+ if (idxCurrentProj < 0 || idxCurrentProj >= count)
+ {
+ return;
+ }
+
+ playlistProjects.removeAt(idxCurrentProj);
+
+ refreshListboxPorjects();
+ playlistProjectsDirty = true;
+}
+
+void DisplayPreferencesPanel::assignPlayPlaylistToGamepad(int idx)
+{
+ if (idx == -1)
+ idx = idxCurrentPlaylist;
+ int count = playlistsLoader.getProjectsInPlaylist(idx, playlistProjects);
+ if (count < 1)
+ {
+ viewer_msg("Playlist is empty.");
+ return;
+ }
+ QList<QString> files;
+ for (int i = 0; i < count; ++i)
+ {
+ QString fname = PlaylistsLoader::convertToAbsoluteFilePath(playlistProjects[i]);
+ if (fname.size() > 0)
+ {
+ files.append(fname);
+ }
+ }
+
+ Gamepad& theGamepad = Gamepad::Instance();
+ theGamepad.SetDemoProjects(files);
+}
+
+void DisplayPreferencesPanel::playPlaylist(int idx)
+{
+ assignPlayPlaylistToGamepad(idx);
+ Gamepad& theGamepad = Gamepad::Instance();
+ theGamepad.SetDemoMode(true);
+}
+
+void DisplayPreferencesPanel::on_btnPlaylistsPlay_clicked()
+{
+ savePlaylistProjects();
+
+ idxCurrentPlaylist = ui.cbPlaylists->currentIndex();
+ if (idxCurrentPlaylist < 0)
+ {
+ viewer_msg("No available playlists.");
+ return;
+ }
+ playPlaylist(idxCurrentPlaylist);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+using namespace nvidia;
+using namespace nvidia::parameterized;
+
+QString PlaylistsLoader::projectPath;
+QString PlaylistsLoader::mediaPath;
+
+#include "FoundationHolder.h"
+
+struct PlaylistParamsContext
+{
+ //nvidia::NvFoundation* mFoundation;
+ NvParameterized::Traits* mTraits;
+ PlaylistParamsFactory* mPlaylistParamsFactory;
+};
+
+PlaylistsLoader::PlaylistsLoader()
+ :pContext(nullptr)
+{
+}
+
+PlaylistsLoader::~PlaylistsLoader()
+{
+}
+
+void PlaylistsLoader::CreatePlaylistParamsContext()
+{
+ if (pContext)
+ return;
+
+ PlaylistParamsContext* context = new PlaylistParamsContext;
+ //context->mFoundation = FoundationHolder::GetFoundation();
+ FoundationHolder::GetFoundation();
+ //assert(context->mFoundation != NV_NULL);
+
+ context->mTraits = NvParameterized::createTraits();
+ context->mPlaylistParamsFactory = new PlaylistParamsFactory;
+ context->mTraits->registerFactory(*context->mPlaylistParamsFactory);
+ pContext = context;
+}
+
+void PlaylistsLoader::ReleasePlaylistParamsContext()
+{
+ if (pContext)
+ {
+ pContext->mTraits->release();
+ delete pContext->mPlaylistParamsFactory;
+ delete pContext;
+ pContext = nullptr;
+ }
+}
+
+void PlaylistsLoader::loadPlaylistsFromMediaPath()
+{
+ if (projectPath.isEmpty())
+ {
+ QString appDir = qApp->applicationDirPath();
+ QDir dirTmp(appDir);
+ if (dirTmp.cd("./media/playlists"))
+ projectPath = dirTmp.absolutePath();
+ else if (dirTmp.cd("../media/playlists"))
+ projectPath = dirTmp.absolutePath();
+ else if (dirTmp.cd("../../media/playlists"))
+ projectPath = dirTmp.absolutePath();
+ else if (dirTmp.cd("../../media"))
+ {
+ bool ok = dirTmp.mkdir("playlists");
+ if (dirTmp.cd("playlists"))
+ {
+ projectPath = dirTmp.absolutePath();
+ }
+ }
+ if (!projectPath.isEmpty())
+ {
+ if (dirTmp.cd(".."))
+ {
+ mediaPath = dirTmp.absolutePath();
+ }
+ else
+ {
+ mediaPath = projectPath + "/..";
+ }
+ }
+ }
+ if (!projectPath.isEmpty())
+ {
+ playlists.clear();
+
+ QStringList filters;
+ filters << (QString("*.") + sPlaylistExt);
+ QDirIterator dir_iterator(projectPath, filters, QDir::Files | QDir::NoSymLinks, QDirIterator::NoIteratorFlags); //QDirIterator::Subdirectories
+ while (dir_iterator.hasNext())
+ {
+ dir_iterator.next();
+ QFileInfo file_info = dir_iterator.fileInfo();
+ std::string absolute_file_path = file_info.absoluteFilePath().toUtf8().data();
+ playlists.append(file_info);
+ }
+ }
+}
+
+bool PlaylistsLoader::rename(int idx, QString& newBaseName)
+{
+ int count = playlists.size();
+ if (idx >= 0 && idx < count)
+ {
+ QFileInfo& finfo = playlists[idx];
+ QString fn = finfo.baseName().toUpper();
+ QString fnNew = newBaseName.toUpper();
+ if (fn != fnNew)
+ {
+ QFileInfo nfi(projectPath, newBaseName + "." + sPlaylistExt);
+ QString fullNewName = nfi.absoluteFilePath();
+ std::string fntmp = fullNewName.toUtf8().data();
+ bool exist = QFile::exists(fullNewName);
+ if (exist)
+ {
+ return false;
+ }
+ bool ok = QFile::rename(finfo.absoluteFilePath(), fullNewName);
+ if (ok)
+ {
+ finfo.setFile(fullNewName);
+ exist = QFile::exists(fullNewName);
+ if (!exist)
+ {
+ return false;
+ }
+ }
+ return ok;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool PlaylistsLoader::remove(int idx)
+{
+ int count = playlists.size();
+ if (idx >= 0 && idx < count)
+ {
+ QFileInfo& finfo = playlists[idx];
+ std::string fn = finfo.fileName().toUtf8().data();
+ bool ok = QFile::remove(finfo.absoluteFilePath());
+ if (ok)
+ {
+ playlists.removeAt(idx);
+ }
+ return ok;
+ }
+ return false;
+}
+
+bool PlaylistsLoader::saveProjectsInPlaylist(int idx, QList<QString>& projects)
+{
+ int count = playlists.size();
+ if (idx < 0 || idx >= count)
+ return false;
+
+ CreatePlaylistParamsContext();
+ if (!pContext)
+ return false;
+
+ std::string tempFilePath = playlists[idx].absoluteFilePath().toUtf8().data();
+ NvParameterized::XmlSerializer serializer(pContext->mTraits);
+ NvFileBuf* stream = new NvFileBufferBase(tempFilePath.c_str(), NvFileBuf::OPEN_WRITE_ONLY);
+ if (!stream || !stream->isOpen())
+ {
+ // file open error
+ if (stream) stream->release();
+ return false;
+ }
+ NvParameterized::Traits* traits = pContext->mTraits;
+ int numObjects = 0;
+ const int kMaxObjects = 1;
+ NvParameterized::Interface* objects[kMaxObjects];
+
+ PlaylistParams* params = new PlaylistParams(traits);
+ objects[numObjects++] = params;
+ NvParameterized::Interface* iface = static_cast<NvParameterized::Interface*>(params);
+
+ if (1)
+ {
+ nvidia::parameterized::PlaylistParams* params = static_cast<nvidia::parameterized::PlaylistParams*>(iface);
+ nvidia::parameterized::PlaylistParamsNS::ParametersStruct& targetDesc = params->parameters();
+
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle("furprojFilePaths", handle) == NvParameterized::ERROR_NONE)
+ {
+ int num = projects.size();
+
+ std::vector<std::string> strArray;
+ const char** strOutput = new const char*[num];
+
+ for (int i = 0; i < num; i++)
+ {
+ std::string proj = projects[i].toUtf8().data();
+ strArray.push_back(proj);
+ strOutput[i] = strArray[i].c_str();
+ }
+
+ handle.resizeArray(num);
+ handle.setParamStringArray(strOutput, num);
+
+ delete[] strOutput;
+ }
+ }
+
+ NV_ASSERT(numObjects <= kMaxObjects);
+ NvParameterized::Serializer::ErrorType serError = NvParameterized::Serializer::ERROR_NONE;
+ bool isUpdate = false;
+ serError = serializer.serialize(*stream, (const NvParameterized::Interface**)&objects[0], numObjects, isUpdate);
+ for (int idx = 0; idx < numObjects; ++idx)
+ {
+ delete objects[idx];
+ }
+ stream->release();
+ ReleasePlaylistParamsContext();
+ return true;
+}
+
+QString PlaylistsLoader::convertToAbsoluteFilePath(QString& filePath)
+{
+ QString fname;
+ bool bCanBeRelativePath = false;
+ bool bAbsPath = (filePath.indexOf(':') >= 0);
+ if (bAbsPath)
+ {
+ if (QFile::exists(filePath))
+ {
+ fname = filePath;
+ }
+ else
+ {
+ viewer_msg(QString(filePath + " does not exist.").toUtf8().data());
+ }
+ std::string tmp2 = fname.toUtf8().data();
+ return fname;
+ }
+ else
+ {
+ QFileInfo fi(mediaPath + "/" + filePath);
+ fname = fi.absoluteFilePath();
+ if (!QFile::exists(fname))
+ {
+ viewer_msg(QString(filePath + " does not exist.").toUtf8().data());
+ fname = "";
+ }
+ std::string tmp2 = fname.toUtf8().data();
+ return fname;
+ }
+}
+
+QString PlaylistsLoader::convertToSaveingFilePath(QString& filePath)
+{
+ QString fname;
+ bool bCanBeRelativePath = false;
+ bool bAbsPath = (filePath.indexOf(':') >= 0);
+ if (bAbsPath)
+ {
+ if (QFile::exists(filePath))
+ {
+ QFileInfo fi(filePath);
+ int pos = fi.absoluteFilePath().indexOf(mediaPath, Qt::CaseInsensitive);
+ if (pos >= 0)
+ {
+ // convert to relative path
+ fname = filePath.right(filePath.size() - (pos + mediaPath.size() + 1));
+ }
+ else
+ {
+ fname = fi.absoluteFilePath();
+ }
+ }
+ else
+ {
+ fname = "";
+ viewer_msg(QString(filePath + " does not exist.").toUtf8().data());
+ }
+ std::string tmp = fname.toUtf8().data();
+ return fname;
+ }
+ // do more try
+ QString tag = "media";
+ int pos = filePath.indexOf(tag, Qt::CaseInsensitive);
+ if (pos >= 0)
+ {
+ fname = filePath.right(filePath.size() - (pos + tag.size() + 1));
+ }
+ else
+ {
+ fname = filePath;
+ }
+ QFileInfo fi(mediaPath + "/" + fname);
+ std::string tmp = fi.absoluteFilePath().toUtf8().data();
+ if (!QFile::exists(fi.absoluteFilePath()))
+ {
+ viewer_msg(QString(filePath + " does not exist.").toUtf8().data());
+ fname = "";
+ }
+ std::string tmp2 = fname.toUtf8().data();
+ return fname;
+}
+
+int PlaylistsLoader::getProjectsInPlaylist(int idx, QList<QString>& projects)
+{
+ projects.clear();
+
+ int count = playlists.size();
+ if (idx < 0 || idx >= count)
+ return 0;
+
+ CreatePlaylistParamsContext();
+ if (!pContext)
+ return 0;
+
+ std::string tempFilePath = playlists[idx].absoluteFilePath().toUtf8().data();
+ NvFileBuf* stream = new NvFileBufferBase(tempFilePath.c_str(), NvFileBuf::OPEN_READ_ONLY);
+ if (!stream || !stream->isOpen())
+ {
+ // file open error
+ if (stream)
+ stream->release();
+ return 0;
+ }
+
+ NvParameterized::Serializer::DeserializedData data;
+ NvParameterized::Serializer::ErrorType serError = NvParameterized::Serializer::ERROR_NONE;
+ NvParameterized::XmlSerializer serializer(pContext->mTraits);
+ bool isUpdated = false;
+ serError = serializer.deserialize(*stream, data, isUpdated);
+ if (data.size() < 1)
+ {
+ if (stream)
+ stream->release();
+ return 0;
+ }
+
+ for (int idx = 0; idx < (int)data.size(); ++idx)
+ {
+ NvParameterized::Interface* iface = data[idx];
+ if (::strcmp(iface->className(), PlaylistParams::staticClassName()) == 0)
+ {
+ nvidia::parameterized::PlaylistParams* params = static_cast<nvidia::parameterized::PlaylistParams*>(iface);
+ nvidia::parameterized::PlaylistParamsNS::ParametersStruct& srcDesc = params->parameters();
+ NvParameterized::Handle handle(iface);
+ if (iface->getParameterHandle("furprojFilePaths", handle) == NvParameterized::ERROR_NONE)
+ {
+ int arraySize;
+ handle.getArraySize(arraySize);
+ char** strArray = new char*[arraySize];
+ handle.getParamStringArray(strArray, arraySize);
+ for (int idx = 0; idx < arraySize; ++idx)
+ {
+ QString fileName = PlaylistsLoader::convertToSaveingFilePath(QString(strArray[idx]));
+ if (fileName.size() > 0)
+ {
+ std::string tmp = fileName.toUtf8().data();
+ projects.append(fileName);
+ }
+ }
+ delete[] strArray;
+ }
+ }
+ }
+ stream->release();
+ ReleasePlaylistParamsContext();
+ return projects.size();
+}
+
+bool PlaylistsLoader::add(QString& name)
+{
+ int count = playlists.size();
+ for (int i = 0; i < count; ++i)
+ {
+ QFileInfo& fi = playlists[i];
+ if (fi.baseName().toUpper() == name.toUpper())
+ {
+ return false;
+ }
+ }
+ QFileInfo nfi(projectPath, name + "." + sPlaylistExt);
+ QFile newFile(nfi.absoluteFilePath());
+ if (newFile.exists())
+ {
+ return false;
+ }
+ newFile.open(QIODevice::WriteOnly);
+ newFile.close();
+ bool exist = QFile::exists(nfi.absoluteFilePath());
+ if (!exist)
+ {
+ return false;
+ }
+ playlists.append(nfi);
+ return true;
+} \ No newline at end of file
diff --git a/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.h b/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.h
new file mode 100644
index 0000000..eb57b12
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/DisplayPreferencesPanel.h
@@ -0,0 +1,100 @@
+#ifndef DisplayPreferencesPanel_h__
+#define DisplayPreferencesPanel_h__
+
+#include <QtWidgets/QWidget>
+#include <QtCore/QDir>
+#include <QtCore/QDirIterator>
+#include "TipListView.h"
+#include "ui_DisplayPreferencesPanel.h"
+
+#include "corelib_global.h"
+
+struct PlaylistParamsContext;
+
+class PlaylistsLoader
+{
+public:
+ PlaylistsLoader();
+ ~PlaylistsLoader();
+
+ void loadPlaylistsFromMediaPath();
+ bool rename(int idx, QString& newName);
+ bool remove(int idx);
+ bool add(QString& name);
+ bool saveProjectsInPlaylist(int idx, QList<QString>& projects);
+ int getProjectsInPlaylist(int idx, QList<QString>& projects);
+
+ static QString convertToSaveingFilePath(QString& filePath);
+ static QString convertToAbsoluteFilePath(QString& filePath);
+
+ QList<QFileInfo> playlists;
+ static QString projectPath;
+ static QString mediaPath;
+
+private:
+ void CreatePlaylistParamsContext();
+ void ReleasePlaylistParamsContext();
+ PlaylistParamsContext* pContext;
+};
+
+class DisplayPreferencesPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DisplayPreferencesPanel(QWidget* parent);
+ ~DisplayPreferencesPanel();
+
+ public:
+ void updateValues();
+
+ public slots:
+ CORELIB_EXPORT void on_spinRenderPlayRateFPS_valueChanged(double v);
+ CORELIB_EXPORT void on_spinSimulationRateFPS_valueChanged(double v);
+ CORELIB_EXPORT void on_spinCameraFOV_valueChanged(double v);
+
+ CORELIB_EXPORT void on_cbSceneUnit_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_cbAntialiasing_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_cbUpAxis_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_cbHandedness_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_cbNavigationStyle_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_btnBackgroundTex_clicked();
+ CORELIB_EXPORT void on_btnBackgroundTexClear_clicked();
+
+ CORELIB_EXPORT void on_cbPlaylists_currentIndexChanged(int index);
+ CORELIB_EXPORT void SelectPlayList(QString& name);
+ CORELIB_EXPORT void on_listWidgetPlaylist_itemSelectionChanged();
+ CORELIB_EXPORT void on_listWidgetPlaylist_itemDoubleClicked(QListWidgetItem* pItem);
+ CORELIB_EXPORT void SelectProject(QString& name);
+
+ CORELIB_EXPORT void on_btnPlaylistsRename_clicked();
+ CORELIB_EXPORT void on_btnPlaylistsAdd_clicked();
+ CORELIB_EXPORT void on_btnPlaylistsReload_clicked();
+ CORELIB_EXPORT void on_btnPlaylistsRemove_clicked();
+
+ CORELIB_EXPORT void on_btnPlaylistAddProj_clicked();
+ CORELIB_EXPORT void on_btnPlaylistProjGoUp_clicked();
+ CORELIB_EXPORT void on_btnPlaylistProjGoDown_clicked();
+ CORELIB_EXPORT void on_btnPlaylistRemoveProj_clicked();
+
+ CORELIB_EXPORT void on_btnPlaylistsPlay_clicked();
+ CORELIB_EXPORT void assignPlayPlaylistToGamepad(int idx = -1);
+ CORELIB_EXPORT void playPlaylist(int idx);
+
+ CORELIB_EXPORT void reloadComboxBoxPlaylists();
+ CORELIB_EXPORT void refreshListboxPorjects();
+ CORELIB_EXPORT void reloadListboxPorjectsFromPlayist();
+ CORELIB_EXPORT void savePlaylistProjects();
+
+ CORELIB_EXPORT void runDemoCommandline();
+
+private:
+ Ui::DisplayPreferencesPanel ui;
+ PlaylistsLoader playlistsLoader;
+ QList<QString> playlistProjects;
+ bool playlistProjectsDirty;
+ int idxCurrentPlaylist;
+ int idxCurrentProj;
+};
+
+#endif // DisplayScene_h__
diff --git a/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.cpp b/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.cpp
new file mode 100644
index 0000000..b118b6b
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.cpp
@@ -0,0 +1,93 @@
+#include "DisplayScenePanel.h"
+
+#include "AppMainWindow.h"
+
+#include "SimpleScene.h"
+#include "GlobalSettings.h"
+
+DisplayScenePanel::DisplayScenePanel(QWidget* parent)
+ :
+ QWidget(parent)
+{
+ ui.setupUi(this);
+}
+
+void DisplayScenePanel::on_btnVisualizeWind_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_visualizeWind = state;
+}
+
+void DisplayScenePanel::on_btnShowGrid_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showGrid = state;
+}
+
+void DisplayScenePanel::on_btnShowAxis_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showAxis = state;
+}
+
+void DisplayScenePanel::on_btnShowWireframe_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showWireframe = state;
+}
+
+void DisplayScenePanel::on_btnUseLighting_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_useLighting = state;
+}
+
+void DisplayScenePanel::on_cbRenderType_currentIndexChanged(int index)
+{
+ GlobalSettings::Inst().m_renderStyle = index;
+}
+
+void DisplayScenePanel::on_btnShowHUD_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showHUD = state;
+}
+
+void DisplayScenePanel::on_btnComputeStats_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_computeStatistics = state;
+}
+
+void DisplayScenePanel::on_btnComputeProfile_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_computeProfile = state;
+}
+
+void DisplayScenePanel::on_btnShowGraphicsMesh_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showGraphicsMesh = state;
+}
+
+void DisplayScenePanel::on_btnShowSkinnedOnly_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_showSkinnedMeshOnly = state;
+ AppMainWindow::Inst().updateUI();
+}
+
+void DisplayScenePanel::on_btnSkinningDQ_stateChanged(int state)
+{
+ GlobalSettings::Inst().m_useDQ = state;
+}
+
+void DisplayScenePanel::on_checkBoxGizmoWithLocal_stateChanged(int state)
+{
+ AppMainWindow::Inst().m_bGizmoWithLocal = state;
+}
+
+void DisplayScenePanel::updateValues()
+{
+ GlobalSettings& globalSettings = GlobalSettings::Inst();
+
+ ui.btnShowGrid->setChecked(globalSettings.m_showGrid);
+ ui.btnShowAxis->setChecked(globalSettings.m_showAxis);
+ ui.cbRenderType->setCurrentIndex(globalSettings.m_renderStyle);
+ ui.btnShowHUD->setChecked(globalSettings.m_showHUD);
+ ui.btnComputeStats->setChecked(globalSettings.m_computeStatistics);
+ ui.btnUseLighting->setChecked(globalSettings.m_useLighting);
+ ui.btnShowGraphicsMesh->setChecked( globalSettings.m_showGraphicsMesh);
+ ui.btnShowSkinnedOnly->setChecked( globalSettings.m_showSkinnedMeshOnly);
+}
diff --git a/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.h b/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.h
new file mode 100644
index 0000000..6614eca
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/DisplayScenePanel.h
@@ -0,0 +1,39 @@
+#ifndef DisplayScenePanel_h__
+#define DisplayScenePanel_h__
+
+#include <QtWidgets/QWidget>
+#include "ui_DisplayScenePanel.h"
+
+#include "corelib_global.h"
+
+class DisplayScenePanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DisplayScenePanel(QWidget* parent);
+
+ public:
+ void updateValues();
+
+ public slots:
+ CORELIB_EXPORT void on_btnVisualizeWind_stateChanged(int state);
+ CORELIB_EXPORT void on_btnShowGrid_stateChanged(int state);
+ CORELIB_EXPORT void on_btnShowAxis_stateChanged(int state);
+ CORELIB_EXPORT void on_cbRenderType_currentIndexChanged(int index);
+ CORELIB_EXPORT void on_btnShowWireframe_stateChanged(int state);
+ CORELIB_EXPORT void on_btnShowHUD_stateChanged(int state);
+ CORELIB_EXPORT void on_btnComputeStats_stateChanged(int state);
+ CORELIB_EXPORT void on_btnComputeProfile_stateChanged(int state);
+ CORELIB_EXPORT void on_btnUseLighting_stateChanged(int state);
+ CORELIB_EXPORT void on_btnShowGraphicsMesh_stateChanged(int state);
+ CORELIB_EXPORT void on_btnShowSkinnedOnly_stateChanged(int state);
+ CORELIB_EXPORT void on_btnSkinningDQ_stateChanged(int state);
+ CORELIB_EXPORT void on_checkBoxGizmoWithLocal_stateChanged(int state);
+
+
+private:
+ Ui::DisplayScenePanel ui;
+};
+
+#endif // DisplayScene_h__
diff --git a/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.cpp b/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.cpp
new file mode 100644
index 0000000..0fe96d1
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.cpp
@@ -0,0 +1,190 @@
+#include <QtWidgets/QLabel>
+#include <QtGui/QImage>
+#include <QtWidgets/QVBoxLayout>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QPaintEvent>
+#include <QtGui/QPainter>
+#include <QtGui/QPainterPath>
+#include "ExpandablePanel.h"
+#include "Nv.h"
+
+static QImage S_TriangleRight;
+static QImage S_TriangleDown;
+
+void InitTriangleResources(int w, int h)
+{
+ S_TriangleRight = QImage(w, h, QImage::Format_ARGB32);
+ S_TriangleDown = QImage(w, h, QImage::Format_ARGB32);
+
+ S_TriangleRight.fill(QColor(0, 0, 0, 0));
+ S_TriangleDown.fill(QColor(0, 0, 0, 0));
+
+ QPainter painter(&S_TriangleRight);
+ painter.setRenderHints(QPainter::Antialiasing,true);
+
+ QPainterPath path;
+ path.moveTo(0, 0);
+ path.lineTo(w, h>>1);
+ path.lineTo(0, h);
+ path.lineTo(0, 0);
+ painter.setPen(Qt::NoPen);
+ painter.fillPath(path, QBrush(QColor(50, 50, 50)));
+
+ // a painter cannot switch device?
+ QPainter painter2(&S_TriangleDown);
+ painter2.setRenderHint(QPainter::Antialiasing,true);
+ path = QPainterPath(); // trick to clear up a path
+ path.moveTo(0, 0);
+ path.lineTo(w, 0);
+ path.lineTo(w>>1, h);
+ path.lineTo(0, 0);
+ painter2.setPen(Qt::NoPen);
+ painter2.fillPath(path, QBrush(QColor(50, 50, 50)));
+}
+
+class TitleLabelImpl : public TitleLabel
+{
+ enum
+ {
+ IMAGE_H = 10,
+ IMAGE_W = 10,
+ FIXED_H = 20,
+ };
+
+public:
+ TitleLabelImpl(QWidget* parent, bool collapsed)
+ : TitleLabel(parent)
+ , _collapsed(collapsed)
+ {
+ QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ sizePolicy.setHorizontalStretch(0);
+ sizePolicy.setVerticalStretch(0);
+ sizePolicy.setHeightForWidth(this->sizePolicy().hasHeightForWidth());
+ this->setSizePolicy(sizePolicy);
+ this->setMinimumSize(QSize(0, FIXED_H));
+ this->setMaximumSize(QSize(16777215, FIXED_H));
+ //this->setStyleSheet(QString::fromUtf8("background:rgb(219,219,219);border:1px solid rgb(185,185,185);"));
+ this->setFrameShape(QFrame::NoFrame);
+ this->setFrameShadow(QFrame::Plain);
+ this->setTextFormat(Qt::AutoText);
+ this->setScaledContents(false);
+ this->setAlignment(Qt::AlignCenter);
+
+ if(S_TriangleDown.isNull() || S_TriangleRight.isNull())
+ InitTriangleResources(IMAGE_W, IMAGE_H);
+ }
+
+ void paintEvent(QPaintEvent * e)
+ {
+ QLabel::paintEvent(e);
+
+ QPainter painter(this);
+ painter.setRenderHints(QPainter::Antialiasing,true);
+
+ const int L = 10;
+ const int T = (FIXED_H - IMAGE_H)/2;
+ QRect rc(L, T, IMAGE_W, IMAGE_H);
+
+ // [later] transform the painter should also work;
+ // but i don't get the expected results, so have to use two images
+ if(_collapsed)
+ painter.drawImage(rc, S_TriangleRight);
+ else
+ painter.drawImage(rc, S_TriangleDown);
+
+ }
+
+ bool Collapsed() {return _collapsed;}
+ void SetCollapsed(bool b)
+ {
+ _collapsed = b;
+ this->update();
+ }
+
+protected:
+ virtual void mousePressEvent(QMouseEvent* e)
+ {
+ if(e->buttons() == Qt::LeftButton)
+ {
+ _collapsed = !_collapsed;
+ this->update();
+ emit LPressSignal();
+ }
+ }
+
+private:
+ bool _collapsed;
+};
+
+ExpandablePanel::ExpandablePanel(QWidget* parent, bool collapsed)
+ : QFrame(parent)
+ , _pContent(NV_NULL)
+{
+ //_pContent = new QWidget(this);
+ Init(collapsed);
+}
+
+ExpandablePanel::ExpandablePanel( QWidget* content, QWidget* parent /*= 0*/ )
+ : QFrame(parent)
+ , _pContent(content)
+{
+ Init();
+}
+
+ExpandablePanel::~ExpandablePanel()
+{
+
+}
+
+void ExpandablePanel::SetCollapsed(bool b)
+{
+ if (_pTitle)
+ _pTitle->SetCollapsed(b);
+}
+
+void ExpandablePanel::Init(bool collapsed)
+{
+ setAutoFillBackground(true);
+ setFrameShape(QFrame::StyledPanel);
+ setFrameShadow(QFrame::Sunken);
+ _pMainLayout = new QVBoxLayout(this);
+ _pMainLayout->setSpacing(2);
+ _pMainLayout->setContentsMargins(0, 0, 0, 0);
+ _pMainLayout->setObjectName(QString::fromUtf8("mainLayout"));
+
+ _pTitle = new TitleLabelImpl(this, collapsed);
+ _pTitle->setText("TitleLabel");
+ _pMainLayout->addWidget(_pTitle);
+
+ connect(_pTitle, SIGNAL(LPressSignal()), this, SLOT(TitlePress()));
+
+ if(_pContent)
+ _pMainLayout->addWidget(_pContent);
+}
+
+void ExpandablePanel::SetTitle( const QString& title )
+{
+ _pTitle->setText(title);
+}
+
+void ExpandablePanel::TitlePress()
+{
+ if(_pTitle->Collapsed())
+ {
+ _pContent->hide();
+ }
+ else // expanded
+ {
+ _pContent->show();
+ }
+}
+
+void ExpandablePanel::AddContent( QWidget* content )
+{
+ // only support one widget as content right now
+ if (_pContent != NV_NULL) return;
+
+ _pMainLayout->addWidget(content);
+ _pContent = content;
+}
+
diff --git a/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.h b/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.h
new file mode 100644
index 0000000..ba3018d
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/ExpandablePanel.h
@@ -0,0 +1,51 @@
+#ifndef ExpandablePanel_h__
+#define ExpandablePanel_h__
+
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QFrame>
+#include <QtWidgets/QLabel>
+
+#include "corelib_global.h"
+
+class TitleLabelImpl;
+class QString;
+class QVBoxLayout;
+
+class TitleLabel : public QLabel
+{
+ Q_OBJECT
+
+public:
+ TitleLabel(QWidget* parent):QLabel(parent){}
+
+signals:
+ void LPressSignal();
+};
+
+class ExpandablePanel : public QFrame
+{
+ Q_OBJECT
+
+public:
+ CORELIB_EXPORT explicit ExpandablePanel(QWidget* parent, bool collapsed = false);
+ explicit ExpandablePanel(QWidget* content, QWidget* parent);
+ virtual ~ExpandablePanel();
+
+ CORELIB_EXPORT void SetTitle(const QString& title);
+ void SetCollapsed(bool b);
+ QWidget* Content() {return _pContent;}
+ CORELIB_EXPORT void AddContent(QWidget* content);
+
+public slots:
+CORELIB_EXPORT void TitlePress();
+
+private:
+ void Init(bool collapsed = false);
+
+private:
+ QVBoxLayout* _pMainLayout;
+ TitleLabelImpl* _pTitle;
+ QWidget* _pContent;
+};
+
+#endif // ExpandablePanel_h__
diff --git a/tools/ArtistTools/source/CoreLib/Window/OutputWindow.cpp b/tools/ArtistTools/source/CoreLib/Window/OutputWindow.cpp
new file mode 100644
index 0000000..08867e3
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/OutputWindow.cpp
@@ -0,0 +1,22 @@
+#include "AppMainWindow.h"
+#include "OutputWindow.h"
+
+#include <QtGUI/QContextMenuEvent>
+
+OutputWindow::OutputWindow(QWidget* parent)
+ :
+ QTextBrowser(parent)
+{
+ ui.setupUi(this);
+}
+
+void OutputWindow::contextMenuEvent(QContextMenuEvent *event)
+{
+ QMenu *menu = createStandardContextMenu();
+
+ QAction* act = new QAction("&Clear All", this);
+ connect(act, SIGNAL(triggered()), this, SLOT(clear()));
+ menu->addAction(act);
+ menu->exec(event->globalPos());
+ delete menu;
+}
diff --git a/tools/ArtistTools/source/CoreLib/Window/OutputWindow.h b/tools/ArtistTools/source/CoreLib/Window/OutputWindow.h
new file mode 100644
index 0000000..5d19bb6
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/OutputWindow.h
@@ -0,0 +1,22 @@
+#ifndef OutputWindow_h__
+#define OutputWindow_h__
+
+#include <QtWidgets/QTextBrowser>
+#include "ui_OutputWindow.h"
+
+#include "UIGlobal.h"
+
+class CORELIB_EXPORT OutputWindow : public QTextBrowser
+{
+ Q_OBJECT
+
+public:
+ OutputWindow(QWidget* parent);
+
+ void contextMenuEvent(QContextMenuEvent *event);
+
+private:
+ Ui::OutputWindow ui;
+};
+
+#endif // DisplayScene_h__
diff --git a/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.cpp b/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.cpp
new file mode 100644
index 0000000..b127f1c
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.cpp
@@ -0,0 +1,17 @@
+#include "SlideSpinBox.h"
+
+void SlideSpinBoxSlots::timeout()
+{
+ //qDebug("%s", __FUNCTION__);
+ this->_cb->on_timeout();
+}
+
+void ConfigSpinBoxInt(SlideSpinBoxInt* spinBox, int minv, int maxv, int step)
+{
+ spinBox->blockSignals(true);
+ spinBox->setRange(minv, maxv);
+ spinBox->setSingleStep(step);
+ spinBox->AutoConfigDragRange();
+ spinBox->setKeyboardTracking(false);
+ spinBox->blockSignals(false);
+}
diff --git a/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.h b/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.h
new file mode 100644
index 0000000..eeb7626
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/SlideSpinBox.h
@@ -0,0 +1,284 @@
+#ifndef SlideSpinBox_h__
+#define SlideSpinBox_h__
+
+#include <QtWidgets/QStyle>
+#include <QtWidgets/QStyleOptionSpinBox>
+#include <QtWidgets/QAbstractSpinBox>
+#include <QtGui/QMouseEvent>
+#include <QtCore/QTimer>
+#include <QtWidgets/QDoubleSpinBox>
+#include <QtWidgets/QSpinBox>
+
+#include "corelib_global.h"
+
+/*
+ A Lesson: never use a template to sub-class QWidgets!
+ Qt doesn't moc template widget classes;
+ So we have to use a specific 'slots-callback' pair to let the moc system work...
+ */
+class SlideSpinBoxCallback
+{
+public:
+ virtual void on_timeout() = 0;
+};
+
+class SlideSpinBoxSlots : public QObject
+{
+ Q_OBJECT
+
+public:
+ SlideSpinBoxSlots(SlideSpinBoxCallback* cb)
+ : _cb (cb)
+ {}
+
+ public slots:
+ CORELIB_EXPORT void timeout();
+
+private:
+ SlideSpinBoxCallback* _cb;
+};
+
+template<typename SpinWidget, typename ValueType>
+class SlideSpinBox : public SpinWidget, public SlideSpinBoxCallback
+{
+
+public:
+ void on_timeout()
+ {
+ //qDebug("%s", __FUNCTION__);
+ EmitDragValueChanged();
+ }
+
+public:
+ typedef ValueType value_type;
+
+ SlideSpinBox(QWidget* parent = 0)
+ : SpinWidget(parent)
+ , _dragRange(DEFAULT_DRAG_RANGE)
+ {
+ setAccelerated(true);
+
+ ResetCustState();
+
+ _pSlots = new SlideSpinBoxSlots(this);
+
+ _dragTimer.setParent(this);
+ _dragTimer.setInterval(DRAG_TIMER_INTERVAL);
+ _dragTimer.setSingleShot(true);
+ connect(&_dragTimer, SIGNAL(timeout()), _pSlots, SLOT(timeout()));
+ }
+
+ ~SlideSpinBox()
+ {
+ delete _pSlots;
+ }
+
+ void SetDragRange(int range)
+ {
+ if(range < MIN_DRAG_RANGE)
+ range = MIN_DRAG_RANGE;
+ else if(range > MAX_DRAG_RANGE)
+ range = MAX_DRAG_RANGE;
+
+ _dragRange = range;
+ }
+
+ void AutoConfigDragRange()
+ {
+ ValueType minv = this->minimum();
+ ValueType maxv = this->maximum();
+
+ double vrange = maxv - minv;
+ double step = 1.0;
+
+ if(vrange <= 1.0)
+ {
+ step = 0.01;
+ }
+ else if(vrange <= 10.0)
+ {
+ step = 0.1;
+ }
+
+ double pixelError = 2.0;
+ double dragRange = vrange * pixelError / step;
+
+ SetDragRange((int)dragRange);
+ }
+
+protected:
+ void mouseMoveEvent ( QMouseEvent * event )
+ {
+ if(!_dragBegin)
+ {
+ QAbstractSpinBox::mouseMoveEvent(event);
+ return;
+ }
+
+ if(!_dragging)
+ {
+ _dragging = true;
+ _cursor = this->cursor();
+
+ this->setCursor(Qt::SizeVerCursor);
+ }
+
+ //if(_dragging)
+ //{
+ // _dragTimer.start(); // always restart, we only need the timeout event;
+ //}
+
+ event->accept();
+ DragValue(event->pos());
+ }
+
+ void mousePressEvent( QMouseEvent * event )
+ {
+ if(event->button() == Qt::LeftButton)
+ {
+ SetupCustState(event);
+ }
+
+ if(_dragging)
+ blockSignals(true);
+ QAbstractSpinBox::mousePressEvent(event);
+ if(_dragging)
+ blockSignals(false);
+ }
+
+ void mouseReleaseEvent( QMouseEvent * event )
+ {
+ if(_dragging)
+ {
+ setCursor(_cursor);
+ _dragTimer.stop();
+ }
+
+ QAbstractSpinBox::mouseReleaseEvent(event);
+ //if(_dragBegin)
+ // EmitDragValueChanged();
+
+ ResetCustState();
+ }
+
+ void timerEvent(QTimerEvent *event)
+ {
+ if(_dragging)
+ {
+ // stop timer event to disable acceleration/auto-stepping
+ event->ignore();
+ return;
+ }
+
+ event->accept();
+
+ if(_dragBegin) blockSignals(true);
+ QAbstractSpinBox::timerEvent(event);
+ if(_dragBegin) blockSignals(false);
+ }
+
+private:
+ enum
+ {
+ MIN_DRAG_RANGE = 50,
+ MAX_DRAG_RANGE = 500,
+
+ DEFAULT_DRAG_RANGE = 100,
+
+ DRAG_TIMER_INTERVAL= 30, // in msec
+ };
+
+ bool SetupCustState(QMouseEvent* event)
+ {
+ QStyleOptionSpinBox opt;
+ this->initStyleOption(&opt);
+ QStyle::SubControl hitControl = this->style()->hitTestComplexControl(QStyle::CC_SpinBox, &opt, event->pos());
+ if(hitControl != QStyle::SC_SpinBoxUp && hitControl != QStyle::SC_SpinBoxDown)
+ return false;
+
+ _pressPosition = event->pos();
+ _dragging = false;
+ _dragBegin = true;
+ _pressValue = this->value();
+ _dragValue = this->value();
+
+ return true;
+ }
+
+ void ResetCustState()
+ {
+ _dragBegin = false;
+ _dragging = false;
+ }
+
+ void DragValue(const QPoint& pos)
+ {
+ ValueType valueRange = this->maximum() - this->minimum();
+
+ double dh = (double)(_pressPosition.y() - pos.y());
+ double dv = valueRange * dh / (double)_dragRange;
+ ValueType v = _pressValue + (ValueType)dv;
+
+ //blockSignals(true);
+ setValue(v);
+ //blockSignals(false);
+ }
+
+ void EmitDragValueChanged()
+ {
+ //if(this->value() != _pressValue) // value are always bound by qt (and decimal settings)
+ if(this->value() != _dragValue)
+ {
+ _dragValue = this->value();
+ emit valueChanged(this->value());
+ }
+ }
+
+ int _dragRange;
+
+ QPoint _pressPosition;
+ ValueType _pressValue;
+ ValueType _dragValue;
+
+ bool _dragging;
+ bool _dragBegin;
+ QCursor _cursor;
+
+ QTimer _dragTimer;
+ SlideSpinBoxSlots* _pSlots;
+};
+
+typedef SlideSpinBox<QDoubleSpinBox, double> SlideSpinBoxF;
+typedef SlideSpinBox<QSpinBox, int> SlideSpinBoxInt;
+
+template<typename CustSpinBox>
+class ConfigSpinBox
+{
+public:
+ typedef typename CustSpinBox::value_type ValueType;
+
+ ConfigSpinBox(CustSpinBox* spinBox, ValueType minv, ValueType maxv, ValueType step = (ValueType)1)
+ {
+ spinBox->blockSignals(true);
+ spinBox->setRange(minv, maxv);
+ spinBox->setSingleStep(step);
+ spinBox->AutoConfigDragRange();
+ spinBox->setKeyboardTracking(false);
+ SpecificConfig<ValueType>(spinBox);
+ spinBox->blockSignals(false);
+ }
+
+ template<typename T>
+ void SpecificConfig(CustSpinBox* spinBox){}
+
+ template<>
+ void SpecificConfig<double>(CustSpinBox* spinBox)
+ {
+ spinBox->setDecimals(2.0);
+ }
+};
+
+#include "corelib_global.h"
+CORELIB_EXPORT void ConfigSpinBoxInt(SlideSpinBoxInt* spinBox, int minv, int maxv, int step = (int)1);
+
+#endif // SlideSpinBox_h__
diff --git a/tools/ArtistTools/source/CoreLib/Window/SlideSpinBoxInt.h b/tools/ArtistTools/source/CoreLib/Window/SlideSpinBoxInt.h
new file mode 100644
index 0000000..393adee
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/SlideSpinBoxInt.h
@@ -0,0 +1,15 @@
+#ifndef SlideSpinBoxInt_h__
+#define SlideSpinBoxInt_h__
+
+#include <QtWidgets/QStyle>
+#include <QtWidgets/QStyleOptionSpinBox>
+#include <QtWidgets/QAbstractSpinBox>
+#include <QtGui/QMouseEvent>
+#include <QtCore/QTimer>
+#include <QtWidgets/QDoubleSpinBox>
+#include <QtWidgets/QSpinBox>
+#include <SlideSpinBox.h>
+
+// use this header as a trick to make moc work right
+
+#endif // SlideSpinBoxInt_h__
diff --git a/tools/ArtistTools/source/CoreLib/Window/TipListView.cpp b/tools/ArtistTools/source/CoreLib/Window/TipListView.cpp
new file mode 100644
index 0000000..b91fd3e
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/TipListView.cpp
@@ -0,0 +1,42 @@
+#include "TipListView.h"
+#include <QtWidgets/QToolTip>
+#include <QtCore/QEvent>
+#include <QtGUI/QEvent.h>
+
+
+TipListView::TipListView(QWidget* parent)
+ :QListWidget(parent)
+{
+}
+
+void TipListView::setTips(QStringList& tips)
+{
+ mTips = tips;
+}
+
+bool TipListView::event(QEvent *evt)
+{
+ if (evt->type() == QEvent::ToolTip)
+ {
+ if (mTips.size() > 0)
+ {
+ QHelpEvent *helpEvent = (QHelpEvent *)(evt);
+ const QPoint& pos = helpEvent->pos();
+ QListWidgetItem* pItem = itemAt(pos);
+ int index = 0, num = count();
+ for (int i = 0; i < num; ++i)
+ {
+ QListWidgetItem* pi = item(i);
+ if (pi == pItem && mTips.size() > i)
+ {
+ QToolTip::showText(helpEvent->globalPos(), mTips[i]);
+ return true;
+ }
+ }
+ }
+ //QToolTip::hideText();
+ //evt->ignore();
+ //return true;
+ }
+ return QListWidget::event(evt);
+}
diff --git a/tools/ArtistTools/source/CoreLib/Window/TipListView.h b/tools/ArtistTools/source/CoreLib/Window/TipListView.h
new file mode 100644
index 0000000..6913baa
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/TipListView.h
@@ -0,0 +1,26 @@
+#ifndef TipListView_h__
+#define TipListView_h__
+
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QListWidget>
+#include <QtCore/QEvent>
+
+#include "corelib_global.h"
+
+class TipListView : public QListWidget
+{
+ Q_OBJECT
+
+public:
+ TipListView(QWidget* parent = 0);
+
+ void setTips(QStringList& tips);
+
+protected:
+ bool event(QEvent *);
+private:
+
+ QStringList mTips;
+
+};
+#endif // TipListView_h__
diff --git a/tools/ArtistTools/source/CoreLib/Window/UIGlobal.h b/tools/ArtistTools/source/CoreLib/Window/UIGlobal.h
new file mode 100644
index 0000000..3d50132
--- /dev/null
+++ b/tools/ArtistTools/source/CoreLib/Window/UIGlobal.h
@@ -0,0 +1,37 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2013-2015 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+#pragma once
+
+#define USE_MATERIAL_SET 1
+#define USE_CURVE_EDITOR 0
+#define USE_TEXTURE_BRIGHTNESS 0
+
+#define USE_INTERNAL_GRAPHICAL_MATERIAL 0
+
+#include "corelib_global.h" \ No newline at end of file