Added widget for toggling quickplay properties

This commit is contained in:
Aruki 2019-04-07 00:00:33 -07:00
parent 7de85a5a2d
commit 42d079ff49
12 changed files with 344 additions and 51 deletions

View File

@ -70,17 +70,17 @@ bool CEditorApplication::CloseAllEditors()
bool CEditorApplication::CloseProject() bool CEditorApplication::CloseProject()
{ {
if (mpActiveProject && CloseAllEditors()) if (mpActiveProject && !CloseAllEditors())
{ return false;
// Close any active quickplay sessions
NDolphinIntegration::KillQuickplay();
// Emit before actually deleting the project to allow editor references to clean up // Close any active quickplay sessions
CGameProject *pOldProj = mpActiveProject; NDolphinIntegration::KillQuickplay();
mpActiveProject = nullptr;
emit ActiveProjectChanged(nullptr); // Emit before actually deleting the project to allow editor references to clean up
delete pOldProj; CGameProject *pOldProj = mpActiveProject;
} mpActiveProject = nullptr;
emit ActiveProjectChanged(nullptr);
delete pOldProj;
return true; return true;
} }
@ -255,6 +255,22 @@ bool CEditorApplication::CookPackageList(QList<CPackage*> PackageList)
else return true; else return true;
} }
bool CEditorApplication::HasAnyDirtyPackages()
{
if (!mpActiveProject)
return false;
for (uint32 PkgIdx = 0; PkgIdx < mpActiveProject->NumPackages(); PkgIdx++)
{
CPackage *pPackage = mpActiveProject->PackageByIndex(PkgIdx);
if (pPackage->NeedsRecook())
return true;
}
return false;
}
bool CEditorApplication::RebuildResourceDatabase() bool CEditorApplication::RebuildResourceDatabase()
{ {
// Make sure all editors are closed // Make sure all editors are closed

View File

@ -43,6 +43,7 @@ public:
bool CookPackage(CPackage *pPackage); bool CookPackage(CPackage *pPackage);
bool CookAllDirtyPackages(); bool CookAllDirtyPackages();
bool CookPackageList(QList<CPackage*> PackageList); bool CookPackageList(QList<CPackage*> PackageList);
bool HasAnyDirtyPackages();
bool RebuildResourceDatabase(); bool RebuildResourceDatabase();

View File

@ -0,0 +1,98 @@
#include "CQuickplayPropertyEditor.h"
#include "ui_CQuickplayPropertyEditor.h"
#include "UICommon.h"
#include <QFileInfo>
/** Validator class for Dolphin line edit */
class CDolphinValidator : public QValidator
{
public:
CDolphinValidator(QObject* pParent = 0) : QValidator(pParent) {}
virtual QValidator::State validate(QString& Input, int& Pos) const override
{
return PathValid(Input) ? QValidator::Acceptable : QValidator::Invalid;
}
static bool PathValid(const QString& kPath)
{
QFileInfo FileInfo(kPath);
return FileInfo.exists() && FileInfo.suffix() == "exe";
}
};
/** CQuickplayPropertyEditor functions */
CQuickplayPropertyEditor::CQuickplayPropertyEditor(SQuickplayParameters& Parameters, QWidget* pParent /*= 0*/)
: QMenu(pParent)
, mpUI(new Ui::CQuickplayPropertyEditor)
, mParameters(Parameters)
{
mpUI->setupUi(this);
setMinimumWidth(300);
NDolphinIntegration::LoadQuickplayParameters(Parameters);
mpUI->DolphinPathLineEdit->setText( NDolphinIntegration::GetDolphinPath() );
mpUI->DolphinPathLineEdit->setValidator( new CDolphinValidator(this) );
mpUI->BootToAreaCheckBox->setChecked( Parameters.Features.HasFlag(EQuickplayFeature::JumpToArea) );
mpUI->SpawnAtCameraLocationCheckBox->setChecked( Parameters.Features.HasFlag(EQuickplayFeature::SetSpawnPosition) );
connect(mpUI->DolphinPathLineEdit, SIGNAL(textChanged(QString)),
this, SLOT(OnDolphinPathChanged(QString)));
connect(mpUI->BootToAreaCheckBox, SIGNAL(toggled(bool)),
this, SLOT(OnBootToAreaToggled(bool)));
connect(mpUI->SpawnAtCameraLocationCheckBox, SIGNAL(toggled(bool)),
this, SLOT(OnSpawnAtCameraLocationToggled(bool)));
}
CQuickplayPropertyEditor::~CQuickplayPropertyEditor()
{
delete mpUI;
}
void CQuickplayPropertyEditor::BrowseForDolphin()
{
QString Path = UICommon::OpenFileDialog(this, "Open Dolphin", "Dolphin.exe");
if (!Path.isEmpty())
{
mpUI->DolphinPathLineEdit->setText(Path);
}
}
void CQuickplayPropertyEditor::OnDolphinPathChanged(const QString& kNewPath)
{
if (CDolphinValidator::PathValid(kNewPath))
{
NDolphinIntegration::SetDolphinPath(parentWidget(), kNewPath);
}
}
void CQuickplayPropertyEditor::OnBootToAreaToggled(bool Enabled)
{
if (Enabled)
{
mParameters.Features.SetFlag(EQuickplayFeature::JumpToArea);
}
else
{
mParameters.Features.ClearFlag(EQuickplayFeature::JumpToArea);
}
NDolphinIntegration::SaveQuickplayParameters(mParameters);
}
void CQuickplayPropertyEditor::OnSpawnAtCameraLocationToggled(bool Enabled)
{
if (Enabled)
{
mParameters.Features.SetFlag(EQuickplayFeature::SetSpawnPosition);
}
else
{
mParameters.Features.ClearFlag(EQuickplayFeature::SetSpawnPosition);
}
NDolphinIntegration::SaveQuickplayParameters(mParameters);
}

View File

@ -0,0 +1,32 @@
#ifndef CQUICKPLAYPROPERTYEDITOR_H
#define CQUICKPLAYPROPERTYEDITOR_H
#include <QMenu>
#include "NDolphinIntegration.h"
namespace Ui {
class CQuickplayPropertyEditor;
}
/** Property editor widget for quickplay.
* @todo may want this to use a CPropertyView eventually.
*/
class CQuickplayPropertyEditor : public QMenu
{
Q_OBJECT
Ui::CQuickplayPropertyEditor* mpUI;
SQuickplayParameters& mParameters;
public:
CQuickplayPropertyEditor(SQuickplayParameters& Parameters, QWidget* pParent = 0);
~CQuickplayPropertyEditor();
public slots:
void BrowseForDolphin();
void OnDolphinPathChanged(const QString& kNewPath);
void OnBootToAreaToggled(bool Enabled);
void OnSpawnAtCameraLocationToggled(bool Enabled);
};
#endif // CQUICKPLAYPROPERTYEDITOR_H

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CQuickplayPropertyEditor</class>
<widget class="QMenu" name="CQuickplayPropertyEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>345</width>
<height>94</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="DolphinPathLabel">
<property name="text">
<string>Dolphin Path</string>
</property>
</widget>
</item>
<item>
<widget class="CSoftValidatorLineEdit" name="DolphinPathLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="DolphinBrowseButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="BootToAreaCheckBox">
<property name="text">
<string>Boot to Current Area</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="SpawnAtCameraLocationCheckBox">
<property name="text">
<string>Spawn at Camera Location</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>CSoftValidatorLineEdit</class>
<extends>QLineEdit</extends>
<header>Editor/Widgets/CSoftValidatorLineEdit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -519,7 +519,7 @@ void CSceneViewport::OnPlayFromHere()
if (mpMenuNode) if (mpMenuNode)
{ {
pOwnerWorldEd->LaunchQuickplayFromLocation(mMenuPoint); pOwnerWorldEd->LaunchQuickplayFromLocation(mMenuPoint, true);
} }
else else
{ {

View File

@ -207,7 +207,8 @@ HEADERS += \
Undo/CSaveStoreCommand.h \ Undo/CSaveStoreCommand.h \
CollisionEditor/CCollisionEditor.h \ CollisionEditor/CCollisionEditor.h \
CollisionEditor/CCollisionEditorViewport.h \ CollisionEditor/CCollisionEditorViewport.h \
NDolphinIntegration.h NDolphinIntegration.h \
CQuickplayPropertyEditor.h
# Source Files # Source Files
SOURCES += \ SOURCES += \
@ -286,7 +287,8 @@ SOURCES += \
ScanEditor/CScanEditor.cpp \ ScanEditor/CScanEditor.cpp \
CollisionEditor/CCollisionEditor.cpp \ CollisionEditor/CCollisionEditor.cpp \
CollisionEditor/CCollisionEditorViewport.cpp \ CollisionEditor/CCollisionEditorViewport.cpp \
NDolphinIntegration.cpp NDolphinIntegration.cpp \
CQuickplayPropertyEditor.cpp
# UI Files # UI Files
FORMS += \ FORMS += \
@ -315,7 +317,8 @@ FORMS += \
StringEditor/CStringEditor.ui \ StringEditor/CStringEditor.ui \
CTweakEditor.ui \ CTweakEditor.ui \
ScanEditor/CScanEditor.ui \ ScanEditor/CScanEditor.ui \
CollisionEditor/CCollisionEditor.ui CollisionEditor/CCollisionEditor.ui \
CQuickplayPropertyEditor.ui
# Codegen # Codegen
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen

View File

@ -11,6 +11,8 @@ namespace NDolphinIntegration
/** Constants */ /** Constants */
const char* const gkDolphinPathSetting = "Quickplay/DolphinPath"; const char* const gkDolphinPathSetting = "Quickplay/DolphinPath";
const char* const gkFeaturesSetting = "Quickplay/Features";
const char* const gkRelFileName = "EditorQuickplay.rel"; const char* const gkRelFileName = "EditorQuickplay.rel";
const char* const gkParameterFile = "dbgconfig"; const char* const gkParameterFile = "dbgconfig";
const char* const gkDolPath = "sys/main.dol"; const char* const gkDolPath = "sys/main.dol";
@ -20,23 +22,27 @@ const char* const gkDolBackupPath = "sys/main.original.dol";
QString gDolphinPath; QString gDolphinPath;
/** The current Dolphin quickplay process */ /** The current Dolphin quickplay process */
QProcess gDolphinProcess; QProcess* gpDolphinProcess = nullptr;
/** The project that the current active quickplay session is running for */ /** The project that the current active quickplay session is running for */
CGameProject* gpQuickplayProject = nullptr; CGameProject* gpQuickplayProject = nullptr;
/** Quickplay relay implementation to detect when the active quickplay session closes */ /** Quickplay relay implementation to detect when the active quickplay session closes */
void CQuickplayRelay::TrackProcess(QProcess* pProcess) void CQuickplayRelay::QuickplayStarted()
{ {
disconnect(this); debugf("Quickplay session started.");
connect(pProcess, SIGNAL(finished(int)), this, SLOT(OnQuickplayFinished(int))); connect(gpDolphinProcess, SIGNAL(finished(int)), this, SLOT(QuickplayFinished(int)));
} }
void CQuickplayRelay::OnQuickplayFinished(int ReturnCode) void CQuickplayRelay::QuickplayFinished(int ReturnCode)
{ {
debugf("Quickplay session finished."); debugf("Quickplay session finished.");
disconnect(this);
disconnect(gpDolphinProcess, 0, this, 0);
CleanupQuickplayFiles(gpQuickplayProject); CleanupQuickplayFiles(gpQuickplayProject);
gpDolphinProcess->waitForFinished();
gpDolphinProcess->deleteLater();
gpDolphinProcess = nullptr;
gpQuickplayProject = nullptr; gpQuickplayProject = nullptr;
} }
@ -62,7 +68,7 @@ EQuickplayLaunchResult LaunchQuickplay(QWidget* pParentWidget,
} }
// Check if quickplay is already running // Check if quickplay is already running
if (gDolphinProcess.state() != QProcess::NotRunning) if (gpDolphinProcess && gpDolphinProcess->state() != QProcess::NotRunning)
{ {
if (UICommon::YesNoQuestion(pParentWidget, "Quickplay", if (UICommon::YesNoQuestion(pParentWidget, "Quickplay",
"Quickplay is already running. Close the existing session and relaunch?")) "Quickplay is already running. Close the existing session and relaunch?"))
@ -80,8 +86,7 @@ EQuickplayLaunchResult LaunchQuickplay(QWidget* pParentWidget,
if (gDolphinPath.isEmpty()) if (gDolphinPath.isEmpty())
{ {
// If the user configured Dolphin on a previous run, it should be stashed in settings // If the user configured Dolphin on a previous run, it should be stashed in settings
QSettings Settings; QString Path = GetDolphinPath();
QString Path = Settings.value(gkDolphinPathSetting).toString();
if (Path.isEmpty()) if (Path.isEmpty())
{ {
@ -99,6 +104,16 @@ EQuickplayLaunchResult LaunchQuickplay(QWidget* pParentWidget,
} }
} }
// Check if the user has any dirty packages
if (gpEdApp->HasAnyDirtyPackages())
{
if (UICommon::YesNoQuestion(pParentWidget, "Uncooked Changes",
"You have uncooked changes. Cook before starting quickplay?"))
{
gpEdApp->CookAllDirtyPackages();
}
}
// All good. Perform initialization tasks. Start by creating the patched dol. // All good. Perform initialization tasks. Start by creating the patched dol.
TString DiscSys = pProject->DiscDir(false) / "sys"; TString DiscSys = pProject->DiscDir(false) / "sys";
std::vector<uint8> DolData; std::vector<uint8> DolData;
@ -139,7 +154,7 @@ EQuickplayLaunchResult LaunchQuickplay(QWidget* pParentWidget,
memcpy(&DolData[PatchOffset], &PatchData[0], PatchData.size()); memcpy(&DolData[PatchOffset], &PatchData[0], PatchData.size());
// These constants are hardcoded for the moment. // These constants are hardcoded for the moment.
// We write the patch to text section 6, which should be at address 0x80002600. // We write the patch to text section 6, which must be at address 0x80002600.
// We hook over the call to LCEnable, which is at offset 0x1D64. // We hook over the call to LCEnable, which is at offset 0x1D64.
CMemoryOutStream Mem(DolData.data(), DolData.size(), EEndian::BigEndian); CMemoryOutStream Mem(DolData.data(), DolData.size(), EEndian::BigEndian);
Mem.GoTo(0x18); Mem.GoTo(0x18);
@ -167,18 +182,20 @@ EQuickplayLaunchResult LaunchQuickplay(QWidget* pParentWidget,
kParms.Write(FSTParmPath); kParms.Write(FSTParmPath);
// We're good to go - launch the quickplay process // We're good to go - launch the quickplay process
gDolphinProcess.start(gDolphinPath, QStringList() << TO_QSTRING(DolPath)); gpDolphinProcess = new QProcess(pParentWidget);
gDolphinProcess.waitForStarted(); gpDolphinProcess->start(gDolphinPath, QStringList() << TO_QSTRING(DolPath));
gpDolphinProcess->waitForStarted();
if (gDolphinProcess.state() != QProcess::Running) if (gpDolphinProcess->state() != QProcess::Running)
{ {
warnf("Quickplay launch failed! Process did not start correctly."); warnf("Quickplay launch failed! Process did not start correctly.");
delete gpDolphinProcess;
gpDolphinProcess = nullptr;
return EQuickplayLaunchResult::Failure; return EQuickplayLaunchResult::Failure;
} }
gQuickplayRelay.TrackProcess(&gDolphinProcess);
gpQuickplayProject = pProject; gpQuickplayProject = pProject;
debugf("Quickplay session started."); gQuickplayRelay.QuickplayStarted();
return EQuickplayLaunchResult::Success; return EQuickplayLaunchResult::Success;
} }
@ -196,10 +213,12 @@ bool IsQuickplaySupported(CGameProject* pProject)
/** Kill the current quickplay process, if it exists. */ /** Kill the current quickplay process, if it exists. */
void KillQuickplay() void KillQuickplay()
{ {
debugf("Killing quickplay."); if (gpDolphinProcess)
gDolphinProcess.close(); {
CleanupQuickplayFiles(gpQuickplayProject); debugf("Stopping active quickplay session.");
gpQuickplayProject = nullptr; gpDolphinProcess->close();
// CQuickplayRelay handles remaining destruction & cleanup
}
} }
/** Clean up any quickplay related file data from the project disc files. */ /** Clean up any quickplay related file data from the project disc files. */
@ -250,4 +269,38 @@ bool SetDolphinPath(QWidget* pParentWidget, const QString& kDolphinPath, bool bS
return true; return true;
} }
/** Retrieves the user path to Dolphin. */
QString GetDolphinPath()
{
// Check if we have a path to Dolphin
QString Path = gDolphinPath;
if (Path.isEmpty())
{
// If the user configured Dolphin on a previous run, it should be stashed in settings
QSettings Settings;
Path = Settings.value(gkDolphinPathSetting).toString();
if (!Path.isEmpty())
{
gDolphinPath = Path;
}
}
return Path;
}
/** Saves/retrieves the given quickplay settings to/from QSettings. */
void SaveQuickplayParameters(const SQuickplayParameters& kParms)
{
QSettings Settings;
Settings.setValue(gkFeaturesSetting, kParms.Features.ToInt32());
}
void LoadQuickplayParameters(SQuickplayParameters& Parms)
{
QSettings Settings;
Parms.Features = Settings.value(gkFeaturesSetting, (uint32) EQuickplayFeature::DefaultFeatures).toInt();
}
} }

View File

@ -13,9 +13,6 @@
// are mirrored in PWEQuickplayPatch and are used by the game. // are mirrored in PWEQuickplayPatch and are used by the game.
// If you modify one, make sure you modify the other. // If you modify one, make sure you modify the other.
namespace NDolphinIntegration
{
/** Return value for LaunchQuickplay */ /** Return value for LaunchQuickplay */
enum class EQuickplayLaunchResult enum class EQuickplayLaunchResult
{ {
@ -33,6 +30,9 @@ enum class EQuickplayFeature
JumpToArea = 0x00000001, JumpToArea = 0x00000001,
/** Spawn the player in the location specified by SpawnTransform */ /** Spawn the player in the location specified by SpawnTransform */
SetSpawnPosition = 0x00000002, SetSpawnPosition = 0x00000002,
/** Flags enabled by default */
DefaultFeatures = JumpToArea | SetSpawnPosition
}; };
DECLARE_FLAGS_ENUMCLASS(EQuickplayFeature, FQuickplayFeatures) DECLARE_FLAGS_ENUMCLASS(EQuickplayFeature, FQuickplayFeatures)
@ -71,17 +71,19 @@ struct SQuickplayParameters
} }
}; };
/** Minimal relay class that detects when the active quickplay session is closed */ namespace NDolphinIntegration
{
/** Minimal relay class for internal use that detects when the active quickplay session is closed */
class CQuickplayRelay : public QObject class CQuickplayRelay : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
CQuickplayRelay() {} CQuickplayRelay() {}
void TrackProcess(QProcess* pProcess);
public slots: public slots:
void OnQuickplayFinished(int ReturnCode); void QuickplayStarted();
void QuickplayFinished(int ReturnCode);
}; };
/** Attempt to launch quickplay based on the current editor state. */ /** Attempt to launch quickplay based on the current editor state. */
@ -103,6 +105,13 @@ bool SetDolphinPath(QWidget* pParentWidget,
const QString& kDolphinPath, const QString& kDolphinPath,
bool bSilent = false); bool bSilent = false);
/** Retrieves the user path to Dolphin. */
QString GetDolphinPath();
/** Saves/retrieves the given quickplay settings to/from QSettings. */
void SaveQuickplayParameters(const SQuickplayParameters& kParms);
void LoadQuickplayParameters(SQuickplayParameters& Parms);
} }
#endif // CQUICKPLAYCONTROLLER_H #endif // CQUICKPLAYCONTROLLER_H

View File

@ -12,6 +12,7 @@
#include "Editor/CExportGameDialog.h" #include "Editor/CExportGameDialog.h"
#include "Editor/CNodeCopyMimeData.h" #include "Editor/CNodeCopyMimeData.h"
#include "Editor/CProjectSettingsDialog.h" #include "Editor/CProjectSettingsDialog.h"
#include "Editor/CQuickplayPropertyEditor.h"
#include "Editor/CSelectionIterator.h" #include "Editor/CSelectionIterator.h"
#include "Editor/UICommon.h" #include "Editor/UICommon.h"
#include "Editor/PropertyEdit/CPropertyView.h" #include "Editor/PropertyEdit/CPropertyView.h"
@ -122,6 +123,11 @@ CWorldEditor::CWorldEditor(QWidget *parent)
// Quickplay buttons // Quickplay buttons
QToolButton* pQuickplayButton = new QToolButton(this); QToolButton* pQuickplayButton = new QToolButton(this);
pQuickplayButton->setIcon( QIcon(":/icons/Play_32px.png") ); pQuickplayButton->setIcon( QIcon(":/icons/Play_32px.png") );
pQuickplayButton->setPopupMode( QToolButton::MenuButtonPopup );
pQuickplayButton->setMenu( new CQuickplayPropertyEditor(mQuickplayParms, this) );
pQuickplayButton->setToolTip( "Quickplay" );
ui->MainToolBar->addSeparator();
mpQuickplayAction = ui->MainToolBar->addWidget(pQuickplayButton); mpQuickplayAction = ui->MainToolBar->addWidget(pQuickplayButton);
mpQuickplayAction->setVisible(false); mpQuickplayAction->setVisible(false);
mpQuickplayAction->setEnabled(false); mpQuickplayAction->setEnabled(false);
@ -950,23 +956,29 @@ void CWorldEditor::UpdateNewLinkLine()
void CWorldEditor::LaunchQuickplay() void CWorldEditor::LaunchQuickplay()
{ {
CVector3f CameraPosition = Viewport()->Camera().Position(); CVector3f CameraPosition = Viewport()->Camera().Position();
LaunchQuickplayFromLocation(CameraPosition); LaunchQuickplayFromLocation(CameraPosition, false);
} }
void CWorldEditor::LaunchQuickplayFromLocation(CVector3f Location) void CWorldEditor::LaunchQuickplayFromLocation(CVector3f Location, bool ForceAsSpawnPosition)
{ {
// This function should not be called if a level is not open in a project. // This function should not be called if a level is not open in a project.
ASSERT( gpEdApp->ActiveProject() != nullptr ); ASSERT( gpEdApp->ActiveProject() != nullptr );
ASSERT( mpWorld && mpArea ); ASSERT( mpWorld && mpArea );
// Fill in parameters and start running // Fill in parameters and start running
mQuickplayParms.BootWorldAssetID = mpWorld->ID().ToLong(); SQuickplayParameters Parameters = mQuickplayParms;
mQuickplayParms.BootAreaAssetID = mpArea->ID().ToLong(); Parameters.BootWorldAssetID = mpWorld->ID().ToLong();
mQuickplayParms.SpawnTransform = Viewport()->Camera().GetCameraTransform(); Parameters.BootAreaAssetID = mpArea->ID().ToLong();
mQuickplayParms.SpawnTransform.SetTranslation(Location); Parameters.SpawnTransform = Viewport()->Camera().GetCameraTransform();
mQuickplayParms.Features.SetFlag(NDolphinIntegration::EQuickplayFeature::JumpToArea); Parameters.SpawnTransform.SetTranslation(Location);
mQuickplayParms.Features.SetFlag(NDolphinIntegration::EQuickplayFeature::SetSpawnPosition);
NDolphinIntegration::LaunchQuickplay(this, gpEdApp->ActiveProject(), mQuickplayParms); if (ForceAsSpawnPosition)
{
Parameters.Features.SetFlag(EQuickplayFeature::JumpToArea);
Parameters.Features.SetFlag(EQuickplayFeature::SetSpawnPosition);
}
NDolphinIntegration::LaunchQuickplay(this, gpEdApp->ActiveProject(), Parameters);
} }
// ************ PROTECTED ************ // ************ PROTECTED ************

View File

@ -67,7 +67,7 @@ class CWorldEditor : public INodeEditor
// Quickplay // Quickplay
QAction* mpQuickplayAction; QAction* mpQuickplayAction;
NDolphinIntegration::SQuickplayParameters mQuickplayParms; SQuickplayParameters mQuickplayParms;
// Sidebars // Sidebars
QVBoxLayout* mpRightSidebarLayout; QVBoxLayout* mpRightSidebarLayout;
@ -136,7 +136,7 @@ public slots:
void UpdateNewLinkLine(); void UpdateNewLinkLine();
void LaunchQuickplay(); void LaunchQuickplay();
void LaunchQuickplayFromLocation(CVector3f Location); void LaunchQuickplayFromLocation(CVector3f Location, bool ForceAsSpawnPosition);
protected: protected:
QAction* AddEditModeButton(QIcon Icon, QString ToolTip, EWorldEditorMode Mode); QAction* AddEditModeButton(QIcon Icon, QString ToolTip, EWorldEditorMode Mode);

View File

@ -1,5 +1,6 @@
#include "CEditorApplication.h" #include "CEditorApplication.h"
#include "CUIRelay.h" #include "CUIRelay.h"
#include "NDolphinIntegration.h"
#include "UICommon.h" #include "UICommon.h"
#include <Common/Log.h> #include <Common/Log.h>
@ -75,6 +76,7 @@ public:
/** Clean up any resources at the end of application execution */ /** Clean up any resources at the end of application execution */
~CMain() ~CMain()
{ {
NDolphinIntegration::KillQuickplay();
NGameList::Shutdown(); NGameList::Shutdown();
} }