Initial work towards making the World Editor the main application window

This commit is contained in:
Aruki 2017-02-11 18:35:33 -07:00
parent 568cd67994
commit 9928a599be
25 changed files with 323 additions and 136 deletions

View File

@ -142,7 +142,8 @@ void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependenc
if (SoundID != -1) if (SoundID != -1)
{ {
SSoundInfo Info = CGameProject::ActiveProject()->AudioManager()->GetSoundInfo(SoundID); CGameProject *pProj = pStruct->Instance()->Area()->Entry()->Project();
SSoundInfo Info = pProj->AudioManager()->GetSoundInfo(SoundID);
if (Info.pAudioGroup) if (Info.pAudioGroup)
{ {

View File

@ -53,8 +53,6 @@ bool CGameExporter::Export(nod::DiscBase *pDisc, const TString& rkOutputDir, CAs
return false; return false;
// Create project // Create project
CGameProject *pOldActiveProj = CGameProject::ActiveProject();
mpProject = CGameProject::CreateProjectForExport( mpProject = CGameProject::CreateProjectForExport(
this, this,
mExportDir, mExportDir,
@ -68,11 +66,13 @@ bool CGameExporter::Export(nod::DiscBase *pDisc, const TString& rkOutputDir, CAs
mFilesystemAddress); mFilesystemAddress);
mpProject->SetProjectName(mGameName); mpProject->SetProjectName(mGameName);
mpProject->SetActive();
mpStore = mpProject->ResourceStore(); mpStore = mpProject->ResourceStore();
mContentDir = mpStore->RawDir(false); mContentDir = mpStore->RawDir(false);
mCookedDir = mpStore->CookedDir(false); mCookedDir = mpStore->CookedDir(false);
CResourceStore *pOldStore = gpResourceStore;
gpResourceStore = mpStore;
// Export game data // Export game data
LoadPaks(); LoadPaks();
ExportCookedResources(); ExportCookedResources();
@ -82,7 +82,7 @@ bool CGameExporter::Export(nod::DiscBase *pDisc, const TString& rkOutputDir, CAs
// Export finished! // Export finished!
mProjectPath = mpProject->ProjectPath(); mProjectPath = mpProject->ProjectPath();
delete mpProject; delete mpProject;
if (pOldActiveProj) pOldActiveProj->SetActive(); if (pOldStore) gpResourceStore = pOldStore;
return true; return true;
} }

View File

@ -3,19 +3,14 @@
#include "Core/Resource/Script/CMasterTemplate.h" #include "Core/Resource/Script/CMasterTemplate.h"
#include <Common/Serialization/XML.h> #include <Common/Serialization/XML.h>
CGameProject *CGameProject::mspActiveProject = nullptr;
CGameProject::~CGameProject() CGameProject::~CGameProject()
{ {
if (mpResourceStore) if (mpResourceStore)
{ {
ASSERT(!mpResourceStore->IsDirty()); ASSERT(!mpResourceStore->IsDirty());
}
if (IsActive()) if (gpResourceStore == mpResourceStore)
{ gpResourceStore = nullptr;
mspActiveProject = nullptr;
gpResourceStore = nullptr;
} }
for (u32 iPkg = 0; iPkg < mPackages.size(); iPkg++) for (u32 iPkg = 0; iPkg < mPackages.size(); iPkg++)
@ -99,15 +94,6 @@ void CGameProject::Serialize(IArchive& rArc)
} }
} }
void CGameProject::SetActive()
{
if (mspActiveProject != this)
{
mspActiveProject = this;
gpResourceStore = mpResourceStore;
}
}
void CGameProject::GetWorldList(std::list<CAssetID>& rOut) const void CGameProject::GetWorldList(std::list<CAssetID>& rOut) const
{ {
for (u32 iPkg = 0; iPkg < mPackages.size(); iPkg++) for (u32 iPkg = 0; iPkg < mPackages.size(); iPkg++)

View File

@ -45,8 +45,6 @@ class CGameProject
eVer_Current = eVer_Max - 1 eVer_Current = eVer_Max - 1
}; };
static CGameProject *mspActiveProject;
// Private Constructor // Private Constructor
CGameProject() CGameProject()
: mProjectName("Unnamed Project") : mProjectName("Unnamed Project")
@ -67,7 +65,6 @@ public:
bool Save(); bool Save();
void Serialize(IArchive& rArc); void Serialize(IArchive& rArc);
void SetActive();
void GetWorldList(std::list<CAssetID>& rOut) const; void GetWorldList(std::list<CAssetID>& rOut) const;
CAssetID FindNamedResource(const TString& rkName) const; CAssetID FindNamedResource(const TString& rkName) const;
@ -107,10 +104,7 @@ public:
inline CAudioManager* AudioManager() const { return mpAudioManager; } inline CAudioManager* AudioManager() const { return mpAudioManager; }
inline EGame Game() const { return mGame; } inline EGame Game() const { return mGame; }
inline float BuildVersion() const { return mBuildVersion; } inline float BuildVersion() const { return mBuildVersion; }
inline bool IsActive() const { return mspActiveProject == this; }
inline bool IsWiiBuild() const { return mBuildVersion >= 3.f; } inline bool IsWiiBuild() const { return mBuildVersion >= 3.f; }
static inline CGameProject* ActiveProject() { return mspActiveProject; }
}; };
#endif // CGAMEPROJECT_H #endif // CGAMEPROJECT_H

View File

@ -497,3 +497,8 @@ void CResourceEntry::RemoveFromProject()
Log::Error("RemoveFromProject called on transient resource entry: " + CookedAssetPath(true)); Log::Error("RemoveFromProject called on transient resource entry: " + CookedAssetPath(true));
} }
} }
CGameProject* CResourceEntry::Project() const
{
return mpStore->Project();
}

View File

@ -11,6 +11,7 @@
class CResource; class CResource;
class CResourceStore; class CResourceStore;
class CGameProject;
class CDependencyTree; class CDependencyTree;
enum EResEntryFlag enum EResEntryFlag
@ -68,6 +69,7 @@ public:
bool Move(const TWideString& rkDir, const TWideString& rkName); bool Move(const TWideString& rkDir, const TWideString& rkName);
void AddToProject(const TWideString& rkDir, const TWideString& rkName); void AddToProject(const TWideString& rkDir, const TWideString& rkName);
void RemoveFromProject(); void RemoveFromProject();
CGameProject* Project() const;
// Accessors // Accessors
void SetDirty() { mFlags.SetFlag(eREF_NeedsRecook); } void SetDirty() { mFlags.SetFlag(eREF_NeedsRecook); }

View File

@ -41,7 +41,7 @@ TResPtr<CTexture> CDrawUtil::mpLightMasks[4];
bool CDrawUtil::mDrawUtilInitialized = false; bool CDrawUtil::mDrawUtilInitialized = false;
// ************ PUBLIC ************ // ************ PUBLIC ************
void CDrawUtil::DrawGrid() void CDrawUtil::DrawGrid(CColor LineColor, CColor BoldLineColor)
{ {
Init(); Init();
@ -55,11 +55,13 @@ void CDrawUtil::DrawGrid()
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
glLineWidth(1.0f); glLineWidth(1.0f);
UseColorShader(CColor(0.6f, 0.6f, 0.6f, 0.f)); LineColor.A = 0.f;
UseColorShader(LineColor);
mGridIndices.DrawElements(0, mGridIndices.GetSize() - 4); mGridIndices.DrawElements(0, mGridIndices.GetSize() - 4);
glLineWidth(1.5f); glLineWidth(1.5f);
UseColorShader(CColor::skTransparentBlack); BoldLineColor.A = 0.f;
UseColorShader(BoldLineColor);
mGridIndices.DrawElements(mGridIndices.GetSize() - 4, 4); mGridIndices.DrawElements(mGridIndices.GetSize() - 4, 4);
} }
@ -405,25 +407,32 @@ void CDrawUtil::Init()
void CDrawUtil::InitGrid() void CDrawUtil::InitGrid()
{ {
Log::Write("Creating grid"); Log::Write("Creating grid");
mGridVertices.SetVertexDesc(ePosition);
mGridVertices.Reserve(64);
for (s32 i = -7; i < 8; i++) const int kGridSize = 501; // must be odd
const float kGridSpacing = 1.f;
int MinIdx = (kGridSize - 1) / -2;
int MaxIdx = (kGridSize - 1) / 2;
mGridVertices.SetVertexDesc(ePosition);
mGridVertices.Reserve(kGridSize * 4);
for (s32 i = MinIdx; i <= MaxIdx; i++)
{ {
if (i == 0) continue; if (i == 0) continue;
mGridVertices.AddVertex(CVector3f(-7.0f, float(i), 0.0f)); mGridVertices.AddVertex(CVector3f(MinIdx * kGridSpacing, i * kGridSpacing, 0.0f));
mGridVertices.AddVertex(CVector3f( 7.0f, float(i), 0.0f)); mGridVertices.AddVertex(CVector3f(MaxIdx * kGridSpacing, i * kGridSpacing, 0.0f));
mGridVertices.AddVertex(CVector3f(float(i), -7.0f, 0.0f)); mGridVertices.AddVertex(CVector3f(i * kGridSpacing, MinIdx * kGridSpacing, 0.0f));
mGridVertices.AddVertex(CVector3f(float(i), 7.0f, 0.0f)); mGridVertices.AddVertex(CVector3f(i * kGridSpacing, MaxIdx * kGridSpacing, 0.0f));
} }
mGridVertices.AddVertex(CVector3f(-7.0f, 0, 0.0f)); mGridVertices.AddVertex(CVector3f(MinIdx * kGridSpacing, 0, 0.0f));
mGridVertices.AddVertex(CVector3f( 7.0f, 0, 0.0f)); mGridVertices.AddVertex(CVector3f(MaxIdx * kGridSpacing, 0, 0.0f));
mGridVertices.AddVertex(CVector3f(0, -7.0f, 0.0f)); mGridVertices.AddVertex(CVector3f(0, MinIdx * kGridSpacing, 0.0f));
mGridVertices.AddVertex(CVector3f(0, 7.0f, 0.0f)); mGridVertices.AddVertex(CVector3f(0, MaxIdx * kGridSpacing, 0.0f));
mGridIndices.Reserve(60); int NumIndices = kGridSize * 4;
for (u16 i = 0; i < 60; i++) mGridIndices.AddIndex(i); mGridIndices.Reserve(NumIndices);
for (u16 i = 0; i < NumIndices; i++) mGridIndices.AddIndex(i);
mGridIndices.SetPrimitiveType(GL_LINES); mGridIndices.SetPrimitiveType(GL_LINES);
} }

View File

@ -57,7 +57,7 @@ class CDrawUtil
static bool mDrawUtilInitialized; static bool mDrawUtilInitialized;
public: public:
static void DrawGrid(); static void DrawGrid(CColor LineColor, CColor BoldLineColor);
static void DrawSquare(); static void DrawSquare();
static void DrawSquare(const CVector2f& TexUL, const CVector2f& TexUR, const CVector2f& TexBR, const CVector2f& TexBL); static void DrawSquare(const CVector2f& TexUL, const CVector2f& TexUR, const CVector2f& TexBR, const CVector2f& TexBL);

View File

@ -67,7 +67,7 @@ void CAnimEventLoader::LoadEvents(IInputStream& rEVNT, bool IsEchoes)
if (SoundID != 0xFFFF) if (SoundID != 0xFFFF)
{ {
SSoundInfo SoundInfo = CGameProject::ActiveProject()->AudioManager()->GetSoundInfo(SoundID); SSoundInfo SoundInfo = mpEventData->Entry()->Project()->AudioManager()->GetSoundInfo(SoundID);
if (SoundInfo.pAudioGroup) if (SoundInfo.pAudioGroup)
mpEventData->AddEvent(CharIndex, SoundInfo.pAudioGroup->ID()); mpEventData->AddEvent(CharIndex, SoundInfo.pAudioGroup->ID());

View File

@ -1298,7 +1298,7 @@ void CUnsupportedParticleLoader::ParseSoundFunction(IInputStream& rFile)
if (SoundID != 0xFFFF) if (SoundID != 0xFFFF)
{ {
SSoundInfo SoundInfo = CGameProject::ActiveProject()->AudioManager()->GetSoundInfo(SoundID); SSoundInfo SoundInfo = mpGroup->Entry()->Project()->AudioManager()->GetSoundInfo(SoundID);
mpGroup->AddDependency(SoundInfo.pAudioGroup); mpGroup->AddDependency(SoundInfo.pAudioGroup);
} }

View File

@ -293,8 +293,6 @@ void CSceneNode::Rotate(const CQuaternion& rkRotation, ETransformSpace Transform
void CSceneNode::Rotate(const CQuaternion& rkRotation, const CVector3f& rkPivot, const CQuaternion& rkPivotRotation, ETransformSpace TransformSpace) void CSceneNode::Rotate(const CQuaternion& rkRotation, const CVector3f& rkPivot, const CQuaternion& rkPivotRotation, ETransformSpace TransformSpace)
{ {
Rotate(rkRotation, TransformSpace);
switch (TransformSpace) switch (TransformSpace)
{ {
case eWorldTransform: case eWorldTransform:
@ -304,7 +302,7 @@ void CSceneNode::Rotate(const CQuaternion& rkRotation, const CVector3f& rkPivot,
mPosition = rkPivot + ((rkPivotRotation * rkRotation * rkPivotRotation.Inverse()) * (mPosition - rkPivot)); mPosition = rkPivot + ((rkPivotRotation * rkRotation * rkPivotRotation.Inverse()) * (mPosition - rkPivot));
break; break;
} }
MarkTransformChanged(); Rotate(rkRotation, TransformSpace);
} }
void CSceneNode::Scale(const CVector3f& rkScale) void CSceneNode::Scale(const CVector3f& rkScale)

View File

@ -13,6 +13,7 @@
CEditorApplication::CEditorApplication(int& rArgc, char **ppArgv) CEditorApplication::CEditorApplication(int& rArgc, char **ppArgv)
: QApplication(rArgc, ppArgv) : QApplication(rArgc, ppArgv)
, mpActiveProject(nullptr)
, mpWorldEditor(nullptr) , mpWorldEditor(nullptr)
, mpResourceBrowser(nullptr) , mpResourceBrowser(nullptr)
, mpProjectDialog(nullptr) , mpProjectDialog(nullptr)
@ -34,9 +35,56 @@ void CEditorApplication::InitEditor()
mpWorldEditor = new CWorldEditor(); mpWorldEditor = new CWorldEditor();
mpResourceBrowser = new CResourceBrowser(mpWorldEditor); mpResourceBrowser = new CResourceBrowser(mpWorldEditor);
mpProjectDialog = new CProjectOverviewDialog(); mpProjectDialog = new CProjectOverviewDialog();
connect(mpProjectDialog, SIGNAL(ActiveProjectChanged(CGameProject*)), mpResourceBrowser, SLOT(UpdateStore())); mpWorldEditor->showMaximized();
}
mpProjectDialog->show(); bool CEditorApplication::CloseProject()
{
if (mpActiveProject)
{
// Close active editor windows. todo: check for unsaved changes
foreach (IEditor *pEditor, mEditorWindows)
{
if (pEditor != mpWorldEditor && !pEditor->close())
return false;
}
// Close world
if (!mpWorldEditor->CloseWorld())
return false;
mpResourceBrowser->close();
mpProjectDialog->close();
delete mpActiveProject;
mpActiveProject = nullptr;
emit ActiveProjectChanged(nullptr);
}
return true;
}
bool CEditorApplication::OpenProject(const QString& rkProjPath)
{
// Close existing project
if (!CloseProject())
return false;
// Load new project
TWideString Path = TO_TWIDESTRING(rkProjPath);
mpActiveProject = CGameProject::LoadProject(Path);
if (mpActiveProject)
{
gpResourceStore = mpActiveProject->ResourceStore();
emit ActiveProjectChanged(mpActiveProject);
return true;
}
else
{
UICommon::ErrorMsg(mpWorldEditor, "Failed to open project! Is it already open in another Prime World Editor instance?");
return false;
}
} }
void CEditorApplication::EditResource(CResourceEntry *pEntry) void CEditorApplication::EditResource(CResourceEntry *pEntry)
@ -58,7 +106,7 @@ void CEditorApplication::EditResource(CResourceEntry *pEntry)
if (!pRes) if (!pRes)
{ {
QMessageBox::warning(nullptr, "Error", "Failed to load resource!"); UICommon::ErrorMsg(mpWorldEditor, "Failed to load resource!");
return; return;
} }
@ -82,7 +130,7 @@ void CEditorApplication::EditResource(CResourceEntry *pEntry)
mEditingMap[pEntry] = pEd; mEditingMap[pEntry] = pEd;
} }
else else
QMessageBox::information(0, "Unsupported Resource", "This resource type is currently unsupported for editing."); UICommon::InfoMsg(mpWorldEditor, "Unsupported Resource", "This resource type is currently unsupported for editing.");
} }
} }
@ -93,19 +141,20 @@ void CEditorApplication::NotifyAssetsModified()
void CEditorApplication::CookAllDirtyPackages() void CEditorApplication::CookAllDirtyPackages()
{ {
CGameProject *pProj = CGameProject::ActiveProject(); ASSERT(mpActiveProject != nullptr);
for (u32 iPkg = 0; iPkg < pProj->NumPackages(); iPkg++) for (u32 iPkg = 0; iPkg < mpActiveProject->NumPackages(); iPkg++)
{ {
CPackage *pPackage = pProj->PackageByIndex(iPkg); CPackage *pPackage = mpActiveProject->PackageByIndex(iPkg);
if (pPackage->NeedsRecook()) if (pPackage->NeedsRecook())
pPackage->Cook(); pPackage->Cook();
} }
mpProjectDialog->SetupPackagesList(); emit PackagesCooked();
} }
// ************ SLOTS ************
void CEditorApplication::AddEditor(IEditor *pEditor) void CEditorApplication::AddEditor(IEditor *pEditor)
{ {
mEditorWindows << pEditor; mEditorWindows << pEditor;
@ -149,7 +198,7 @@ void CEditorApplication::OnEditorClose()
IEditor *pEditor = qobject_cast<IEditor*>(sender()); IEditor *pEditor = qobject_cast<IEditor*>(sender());
ASSERT(pEditor); ASSERT(pEditor);
if (qobject_cast<CWorldEditor*>(pEditor) == nullptr) if (pEditor != mpWorldEditor)
{ {
for (auto Iter = mEditingMap.begin(); Iter != mEditingMap.end(); Iter++) for (auto Iter = mEditingMap.begin(); Iter != mEditingMap.end(); Iter++)
{ {
@ -162,7 +211,7 @@ void CEditorApplication::OnEditorClose()
mEditorWindows.removeOne(pEditor); mEditorWindows.removeOne(pEditor);
delete pEditor; delete pEditor;
}
CGameProject::ActiveProject()->ResourceStore()->DestroyUnreferencedResources(); mpActiveProject->ResourceStore()->DestroyUnreferencedResources();
}
} }

View File

@ -1,6 +1,7 @@
#ifndef CEDITORAPPLICATION_H #ifndef CEDITORAPPLICATION_H
#define CEDITORAPPLICATION_H #define CEDITORAPPLICATION_H
#include <Core/GameProject/CGameProject.h>
#include <QApplication> #include <QApplication>
#include <QTimer> #include <QTimer>
#include <QVector> #include <QVector>
@ -18,23 +19,28 @@ class CEditorApplication : public QApplication
{ {
Q_OBJECT Q_OBJECT
QTimer mRefreshTimer; CGameProject *mpActiveProject;
CWorldEditor *mpWorldEditor; CWorldEditor *mpWorldEditor;
CResourceBrowser *mpResourceBrowser; CResourceBrowser *mpResourceBrowser;
CProjectOverviewDialog *mpProjectDialog; CProjectOverviewDialog *mpProjectDialog;
QVector<IEditor*> mEditorWindows; QVector<IEditor*> mEditorWindows;
QMap<CResourceEntry*,IEditor*> mEditingMap; QMap<CResourceEntry*,IEditor*> mEditingMap;
QTimer mRefreshTimer;
double mLastUpdate; double mLastUpdate;
public: public:
CEditorApplication(int& rArgc, char **ppArgv); CEditorApplication(int& rArgc, char **ppArgv);
~CEditorApplication(); ~CEditorApplication();
void InitEditor(); void InitEditor();
bool CloseProject();
bool OpenProject(const QString& rkProjPath);
void EditResource(CResourceEntry *pEntry); void EditResource(CResourceEntry *pEntry);
void NotifyAssetsModified(); void NotifyAssetsModified();
void CookAllDirtyPackages(); void CookAllDirtyPackages();
// Accessors // Accessors
inline CGameProject* ActiveProject() const { return mpActiveProject; }
inline CWorldEditor* WorldEditor() const { return mpWorldEditor; } inline CWorldEditor* WorldEditor() const { return mpWorldEditor; }
inline CResourceBrowser* ResourceBrowser() const { return mpResourceBrowser; } inline CResourceBrowser* ResourceBrowser() const { return mpResourceBrowser; }
inline CProjectOverviewDialog* ProjectDialog() const { return mpProjectDialog; } inline CProjectOverviewDialog* ProjectDialog() const { return mpProjectDialog; }
@ -48,7 +54,9 @@ public slots:
void OnEditorClose(); void OnEditorClose();
signals: signals:
void ActiveProjectChanged(CGameProject *pNewProj);
void AssetsModified(); void AssetsModified();
void PackagesCooked();
}; };
#define gpEdApp static_cast<CEditorApplication*>(qApp) #define gpEdApp static_cast<CEditorApplication*>(qApp)

View File

@ -7,7 +7,21 @@
// Tiny helper to make sure the grid draws at the correct depth. // Tiny helper to make sure the grid draws at the correct depth.
class CGridRenderable : public IRenderable class CGridRenderable : public IRenderable
{ {
CColor mLineColor;
CColor mBoldLineColor;
public: public:
CGridRenderable()
: mLineColor(0.6f, 0.6f, 0.6f, 0.f)
, mBoldLineColor(0.f, 0.f, 0.f, 0.f)
{}
inline void SetColor(const CColor& rkLineColor, const CColor& rkBoldColor)
{
mLineColor = rkLineColor;
mBoldLineColor = rkBoldColor;
}
void AddToRenderer(CRenderer *pRenderer, const SViewInfo&) void AddToRenderer(CRenderer *pRenderer, const SViewInfo&)
{ {
pRenderer->AddMesh(this, 0, CAABox::skOne, false, eDrawMesh); pRenderer->AddMesh(this, 0, CAABox::skOne, false, eDrawMesh);
@ -15,7 +29,7 @@ public:
void Draw(FRenderOptions, int, ERenderCommand, const SViewInfo&) void Draw(FRenderOptions, int, ERenderCommand, const SViewInfo&)
{ {
CDrawUtil::DrawGrid(); CDrawUtil::DrawGrid(mLineColor, mBoldLineColor);
} }
}; };

View File

@ -32,35 +32,6 @@ CProjectOverviewDialog::~CProjectOverviewDialog()
delete mpUI; delete mpUI;
} }
void CProjectOverviewDialog::InternalLoadProject(const QString& rkPath)
{
// Load project
TWideString Path = TO_TWIDESTRING(rkPath);
CGameProject *pNewProj = CGameProject::LoadProject(Path);
if (pNewProj)
{
if (mpProject) delete mpProject;
mpProject = pNewProj;
mpProject->SetActive();
SetupWorldsList();
SetupPackagesList();
emit ActiveProjectChanged(mpProject);
}
else
{
UICommon::ErrorMsg(this, "Failed to open project! Is it already open in another Prime World Editor instance?");
}
}
void CProjectOverviewDialog::OpenProject()
{
// Open project file
QString ProjPath = UICommon::OpenFileDialog(this, "Open Project", "Game Project (*.prj)");
if (!ProjPath.isEmpty()) InternalLoadProject(ProjPath);
}
void CProjectOverviewDialog::ExportGame() void CProjectOverviewDialog::ExportGame()
{ {
QString IsoPath = UICommon::OpenFileDialog(this, "Select ISO", "*.iso *.gcm *.tgc *.wbfs"); QString IsoPath = UICommon::OpenFileDialog(this, "Select ISO", "*.iso *.gcm *.tgc *.wbfs");
@ -77,14 +48,12 @@ void CProjectOverviewDialog::ExportGame()
int OpenChoice = QMessageBox::information(this, "Export complete", "Export finished successfully! Open new project?", QMessageBox::Yes, QMessageBox::No); int OpenChoice = QMessageBox::information(this, "Export complete", "Export finished successfully! Open new project?", QMessageBox::Yes, QMessageBox::No);
if (OpenChoice == QMessageBox::Yes) if (OpenChoice == QMessageBox::Yes)
InternalLoadProject(ExportDialog.ProjectPath()); gpEdApp->OpenProject(ExportDialog.ProjectPath());
} }
} }
void CProjectOverviewDialog::SetupWorldsList() void CProjectOverviewDialog::SetupWorldsList()
{ {
ASSERT(mpProject != nullptr && mpProject->IsActive());
std::list<CAssetID> WorldIDs; std::list<CAssetID> WorldIDs;
mpProject->GetWorldList(WorldIDs); mpProject->GetWorldList(WorldIDs);
mWorldEntries.clear(); mWorldEntries.clear();
@ -111,7 +80,6 @@ void CProjectOverviewDialog::SetupWorldsList()
void CProjectOverviewDialog::SetupPackagesList() void CProjectOverviewDialog::SetupPackagesList()
{ {
ASSERT(mpProject != nullptr && mpProject->IsActive());
mpUI->PackagesList->clear(); mpUI->PackagesList->clear();
for (u32 iPkg = 0; iPkg < mpProject->NumPackages(); iPkg++) for (u32 iPkg = 0; iPkg < mpProject->NumPackages(); iPkg++)

View File

@ -24,11 +24,7 @@ public:
explicit CProjectOverviewDialog(QWidget *pParent = 0); explicit CProjectOverviewDialog(QWidget *pParent = 0);
~CProjectOverviewDialog(); ~CProjectOverviewDialog();
protected:
void InternalLoadProject(const QString& rkPath);
public slots: public slots:
void OpenProject();
void ExportGame(); void ExportGame();
void LoadWorld(); void LoadWorld();
void LaunchEditor(); void LaunchEditor();

View File

@ -20,6 +20,7 @@ CSceneViewport::CSceneViewport(QWidget *pParent)
, mpContextMenu(nullptr) , mpContextMenu(nullptr)
, mpMenuNode(nullptr) , mpMenuNode(nullptr)
{ {
mGrid.SetColor(CColor(0.f, 0.f, 0.6f, 0.f), CColor(0.f, 0.f, 1.f, 0.f));
mLinkLine.SetColor(CColor::skYellow); mLinkLine.SetColor(CColor::skYellow);
mpRenderer = new CRenderer(); mpRenderer = new CRenderer();
@ -299,6 +300,7 @@ void CSceneViewport::Paint()
{ {
if (!mpScene) return; if (!mpScene) return;
mpRenderer->SetClearColor(CColor::skBlack);
mpRenderer->BeginFrame(); mpRenderer->BeginFrame();
// todo: The sky should really just be a regular node in the background depth group instead of having special rendering code here // todo: The sky should really just be a regular node in the background depth group instead of having special rendering code here
@ -319,6 +321,10 @@ void CSceneViewport::Paint()
pGizmo->AddToRenderer(mpRenderer, mViewInfo); pGizmo->AddToRenderer(mpRenderer, mViewInfo);
} }
// Draw grid if the scene is empty
if (!mViewInfo.GameMode && mpScene->ActiveArea() == nullptr)
mGrid.AddToRenderer(mpRenderer, mViewInfo);
// Draw the line for the link the user is editing. // Draw the line for the link the user is editing.
if (mLinkLineEnabled) mLinkLine.AddToRenderer(mpRenderer, mViewInfo); if (mLinkLineEnabled) mLinkLine.AddToRenderer(mpRenderer, mViewInfo);

View File

@ -2,6 +2,7 @@
#define CSCENEVIEWPORT_H #define CSCENEVIEWPORT_H
#include "CBasicViewport.h" #include "CBasicViewport.h"
#include "CGridRenderable.h"
#include "CLineRenderable.h" #include "CLineRenderable.h"
#include "INodeEditor.h" #include "INodeEditor.h"
@ -40,6 +41,9 @@ class CSceneViewport : public CBasicViewport
QAction *mpSelectConnectedIncomingAction; QAction *mpSelectConnectedIncomingAction;
QAction *mpSelectConnectedAllAction; QAction *mpSelectConnectedAllAction;
// Grid
CGridRenderable mGrid;
// Link Line // Link Line
bool mLinkLineEnabled; bool mLinkLineEnabled;
CLineRenderable mLinkLine; CLineRenderable mLinkLine;

View File

@ -297,7 +297,7 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
u32 SoundID = pSound->Get(); u32 SoundID = pSound->Get();
if (SoundID == -1) return "[None]"; if (SoundID == -1) return "[None]";
CGameProject *pProj = CGameProject::ActiveProject(); CGameProject *pProj = pSound->Instance()->Area()->Entry()->Project();
SSoundInfo SoundInfo = pProj->AudioManager()->GetSoundInfo(SoundID); SSoundInfo SoundInfo = pProj->AudioManager()->GetSoundInfo(SoundID);
QString Out = QString::number(SoundID); QString Out = QString::number(SoundID);

View File

@ -69,14 +69,15 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
QAction *pImportFromContentsTxtAction = new QAction("Import from Pak Contents List", this); QAction *pImportFromContentsTxtAction = new QAction("Import from Pak Contents List", this);
pImportNamesMenu->addAction(pImportFromContentsTxtAction); pImportNamesMenu->addAction(pImportFromContentsTxtAction);
#if !PUBLIC_RELEASE
QAction *pGenerateAssetNamesAction = new QAction("Generate Asset Names", this);
pImportNamesMenu->addAction(pGenerateAssetNamesAction);
#endif
QAction *pImportFromAssetNameMapAction = new QAction("Import from Asset Name Map", this); QAction *pImportFromAssetNameMapAction = new QAction("Import from Asset Name Map", this);
pImportNamesMenu->addAction(pImportFromAssetNameMapAction); pImportNamesMenu->addAction(pImportFromAssetNameMapAction);
QAction *pGenerateAssetNamesAction = new QAction("Generate Asset Names", this);
pImportNamesMenu->addAction(pGenerateAssetNamesAction);
#if !PUBLIC_RELEASE
pGenerateAssetNamesAction->setVisible(false);
#endif
// Set up connections // Set up connections
connect(mpUI->StoreComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateStore())); connect(mpUI->StoreComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateStore()));
connect(mpUI->SearchBar, SIGNAL(textChanged(QString)), this, SLOT(OnSearchStringChanged())); connect(mpUI->SearchBar, SIGNAL(textChanged(QString)), this, SLOT(OnSearchStringChanged()));
@ -87,13 +88,11 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
connect(mpUI->ResourceTableView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnResourceSelectionChanged(QModelIndex, QModelIndex))); connect(mpUI->ResourceTableView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnResourceSelectionChanged(QModelIndex, QModelIndex)));
connect(pImportFromContentsTxtAction, SIGNAL(triggered()), this, SLOT(OnImportPakContentsTxt())); connect(pImportFromContentsTxtAction, SIGNAL(triggered()), this, SLOT(OnImportPakContentsTxt()));
connect(pImportFromAssetNameMapAction, SIGNAL(triggered()), this, SLOT(OnImportNamesFromAssetNameMap())); connect(pImportFromAssetNameMapAction, SIGNAL(triggered()), this, SLOT(OnImportNamesFromAssetNameMap()));
connect(pGenerateAssetNamesAction, SIGNAL(triggered()), this, SLOT(OnGenerateAssetNames()));
connect(mpUI->ExportNamesButton, SIGNAL(clicked()), this, SLOT(ExportAssetNames())); connect(mpUI->ExportNamesButton, SIGNAL(clicked()), this, SLOT(ExportAssetNames()));
connect(&mUpdateFilterTimer, SIGNAL(timeout()), this, SLOT(UpdateFilter())); connect(&mUpdateFilterTimer, SIGNAL(timeout()), this, SLOT(UpdateFilter()));
connect(mpFilterAllBox, SIGNAL(toggled(bool)), this, SLOT(OnFilterTypeBoxTicked(bool))); connect(mpFilterAllBox, SIGNAL(toggled(bool)), this, SLOT(OnFilterTypeBoxTicked(bool)));
connect(gpEdApp, SIGNAL(ActiveProjectChanged(CGameProject*)), this, SLOT(UpdateStore()));
#if !PUBLIC_RELEASE
connect(pGenerateAssetNamesAction, SIGNAL(triggered()), this, SLOT(OnGenerateAssetNames()));
#endif
} }
CResourceBrowser::~CResourceBrowser() CResourceBrowser::~CResourceBrowser()

View File

@ -1,5 +1,6 @@
#include "TestDialog.h" #include "TestDialog.h"
#include "ui_TestDialog.h" #include "ui_TestDialog.h"
#include "CEditorApplication.h"
#include <Core/GameProject/CGameProject.h> #include <Core/GameProject/CGameProject.h>
TestDialog::TestDialog(QWidget *pParent) TestDialog::TestDialog(QWidget *pParent)
@ -26,7 +27,7 @@ void TestDialog::OnSpinBoxChanged(int NewValue)
void TestDialog::OnFind() void TestDialog::OnFind()
{ {
u32 SoundID = ui->spinBox->value(); u32 SoundID = ui->spinBox->value();
CGameProject *pProj = CGameProject::ActiveProject(); CGameProject *pProj = gpEdApp->ActiveProject();
if (pProj) if (pProj)
{ {

View File

@ -17,17 +17,16 @@
#include "Editor/Widgets/WVectorEditor.h" #include "Editor/Widgets/WVectorEditor.h"
#include "Editor/Undo/UndoCommands.h" #include "Editor/Undo/UndoCommands.h"
#include <Common/Log.h>
#include <Core/GameProject/CGameProject.h> #include <Core/GameProject/CGameProject.h>
#include <Core/Render/CDrawUtil.h> #include <Core/Render/CDrawUtil.h>
#include <Core/Scene/CSceneIterator.h> #include <Core/Scene/CSceneIterator.h>
#include <Common/Log.h>
#include <iostream>
#include <QClipboard> #include <QClipboard>
#include <QComboBox> #include <QComboBox>
#include <QFontMetrics> #include <QFontMetrics>
#include <QMessageBox> #include <QMessageBox>
#include <QOpenGLContext> #include <QSettings>
CWorldEditor::CWorldEditor(QWidget *parent) CWorldEditor::CWorldEditor(QWidget *parent)
: INodeEditor(parent) : INodeEditor(parent)
@ -90,7 +89,25 @@ CWorldEditor::CWorldEditor(QWidget *parent)
mpCollisionDialog = new CCollisionRenderSettingsDialog(this, this); mpCollisionDialog = new CCollisionRenderSettingsDialog(this, this);
// "Open Recent" menu
mpOpenRecentMenu = new QMenu(this);
ui->ActionOpenRecent->setMenu(mpOpenRecentMenu);
for (u32 iAct = 0; iAct < mskMaxRecentProjects; iAct++)
{
QAction *pAction = new QAction(this);
pAction->setVisible(false);
connect(pAction, SIGNAL(triggered(bool)), this, SLOT(OpenRecentProject()));
mpOpenRecentMenu->addAction(pAction);
mRecentProjectsActions[iAct] = pAction;
}
UpdateOpenRecentActions();
// Connect signals and slots // Connect signals and slots
connect(gpEdApp, SIGNAL(ActiveProjectChanged(CGameProject*)), this, SLOT(OnActiveProjectChanged(CGameProject*)));
connect(gpEdApp->clipboard(), SIGNAL(dataChanged()), this, SLOT(OnClipboardDataModified()));
connect(ui->MainViewport, SIGNAL(ViewportClick(SRayIntersection,QMouseEvent*)), this, SLOT(OnViewportClick(SRayIntersection,QMouseEvent*))); connect(ui->MainViewport, SIGNAL(ViewportClick(SRayIntersection,QMouseEvent*)), this, SLOT(OnViewportClick(SRayIntersection,QMouseEvent*)));
connect(ui->MainViewport, SIGNAL(InputProcessed(SRayIntersection,QMouseEvent*)), this, SLOT(OnViewportInputProcessed(SRayIntersection,QMouseEvent*))); connect(ui->MainViewport, SIGNAL(InputProcessed(SRayIntersection,QMouseEvent*)), this, SLOT(OnViewportInputProcessed(SRayIntersection,QMouseEvent*)));
connect(ui->MainViewport, SIGNAL(InputProcessed(SRayIntersection,QMouseEvent*)), this, SLOT(UpdateGizmoUI()) ); connect(ui->MainViewport, SIGNAL(InputProcessed(SRayIntersection,QMouseEvent*)), this, SLOT(UpdateGizmoUI()) );
@ -105,10 +122,10 @@ CWorldEditor::CWorldEditor(QWidget *parent)
connect(ui->TransformSpinBox, SIGNAL(ValueChanged(CVector3f)), this, SLOT(OnTransformSpinBoxModified(CVector3f))); connect(ui->TransformSpinBox, SIGNAL(ValueChanged(CVector3f)), this, SLOT(OnTransformSpinBoxModified(CVector3f)));
connect(ui->TransformSpinBox, SIGNAL(EditingDone(CVector3f)), this, SLOT(OnTransformSpinBoxEdited(CVector3f))); connect(ui->TransformSpinBox, SIGNAL(EditingDone(CVector3f)), this, SLOT(OnTransformSpinBoxEdited(CVector3f)));
connect(ui->CamSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnCameraSpeedChange(double))); connect(ui->CamSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnCameraSpeedChange(double)));
connect(qApp->clipboard(), SIGNAL(dataChanged()), this, SLOT(OnClipboardDataModified()));
connect(&mUndoStack, SIGNAL(indexChanged(int)), this, SLOT(OnUndoStackIndexChanged())); connect(&mUndoStack, SIGNAL(indexChanged(int)), this, SLOT(OnUndoStackIndexChanged()));
connect(ui->ActionSave, SIGNAL(triggered()), this, SLOT(Save())); connect(ui->ActionOpenProject, SIGNAL(triggered()), this, SLOT(OpenProject()));
connect(ui->ActionSave, SIGNAL(triggered()) , this, SLOT(Save()));
connect(ui->ActionSaveAndRepack, SIGNAL(triggered()), this, SLOT(SaveAndRepack())); connect(ui->ActionSaveAndRepack, SIGNAL(triggered()), this, SLOT(SaveAndRepack()));
connect(ui->ActionCut, SIGNAL(triggered()), this, SLOT(Cut())); connect(ui->ActionCut, SIGNAL(triggered()), this, SLOT(Cut()));
connect(ui->ActionCopy, SIGNAL(triggered()), this, SLOT(Copy())); connect(ui->ActionCopy, SIGNAL(triggered()), this, SLOT(Copy()));
@ -172,6 +189,34 @@ void CWorldEditor::closeEvent(QCloseEvent *pEvent)
} }
} }
bool CWorldEditor::CloseWorld()
{
if (CheckUnsavedChanges())
{
ExitPickMode();
ClearSelection();
ui->MainViewport->ResetHover();
ui->ModifyTabContents->ClearUI();
ui->InstancesTabContents->SetMaster(nullptr);
mUndoStack.clear();
mpCollisionDialog->close();
mpLinkDialog->close();
if (mpPoiDialog)
mpPoiDialog->close();
// Clear old area - hack until better world/area loader is implemented
if (mpArea)
mpArea->ClearScriptLayers();
mpArea = nullptr;
mpWorld = nullptr;
return true;
}
else return false;
}
void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea) void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
{ {
ExitPickMode(); ExitPickMode();
@ -188,10 +233,6 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
mpPoiDialog = nullptr; mpPoiDialog = nullptr;
} }
// Clear old area - hack until better world/area loader is implemented
if ((mpArea) && (pArea != mpArea))
mpArea->ClearScriptLayers();
// Load new area // Load new area
mpArea = pArea; mpArea = pArea;
mpWorld = pWorld; mpWorld = pWorld;
@ -355,6 +396,32 @@ void CWorldEditor::Paste()
} }
} }
void CWorldEditor::OpenProject()
{
QString ProjPath = UICommon::OpenFileDialog(this, "Open Project", "Game Project (*.prj)");
if (!ProjPath.isEmpty()) gpEdApp->OpenProject(ProjPath);
}
void CWorldEditor::OpenRecentProject()
{
QAction *pSender = qobject_cast<QAction*>(sender());
if (pSender)
{
QSettings Settings;
QStringList RecentProjectsList = Settings.value("WorldEditor/RecentProjectsList").toStringList();
int ProjIndex = pSender->data().toInt();
QString ProjPath = RecentProjectsList[ProjIndex];
gpEdApp->OpenProject(ProjPath);
}
}
void CWorldEditor::CloseProject()
{
gpEdApp->CloseProject();
}
bool CWorldEditor::Save() bool CWorldEditor::Save()
{ {
bool SaveAreaSuccess = mpArea->Entry()->Save(); bool SaveAreaSuccess = mpArea->Entry()->Save();
@ -384,6 +451,22 @@ bool CWorldEditor::SaveAndRepack()
return true; return true;
} }
void CWorldEditor::OnActiveProjectChanged(CGameProject *pProj)
{
ui->ActionCloseProject->setEnabled( pProj != nullptr );
if (!pProj) return;
// Update recent projects list
QSettings Settings;
QStringList RecentProjectsList = Settings.value("WorldEditor/RecentProjectsList").toStringList();
QString ProjPath = TO_QSTRING(pProj->ProjectPath());
RecentProjectsList.removeAll(ProjPath);
RecentProjectsList.prepend(ProjPath);
Settings.setValue("WorldEditor/RecentProjectsList", RecentProjectsList);
UpdateOpenRecentActions();
}
void CWorldEditor::OnLinksModified(const QList<CScriptObject*>& rkInstances) void CWorldEditor::OnLinksModified(const QList<CScriptObject*>& rkInstances)
{ {
foreach (CScriptObject *pInstance, rkInstances) foreach (CScriptObject *pInstance, rkInstances)
@ -509,6 +592,27 @@ void CWorldEditor::DeleteSelection()
} }
} }
void CWorldEditor::UpdateOpenRecentActions()
{
QSettings Settings;
QStringList RecentProjectsList = Settings.value("WorldEditor/RecentProjectsList").toStringList();
for (int iProj = 0; iProj < mskMaxRecentProjects; iProj++)
{
QAction *pAction = mRecentProjectsActions[iProj];
if (iProj < RecentProjectsList.size())
{
QString ActionText = QString("&%1 %2").arg(iProj).arg(RecentProjectsList[iProj]);
pAction->setText(ActionText);
pAction->setVisible(true);
}
else
pAction->setVisible(false);
}
}
void CWorldEditor::UpdateStatusBar() void CWorldEditor::UpdateStatusBar()
{ {
// Would be cool to do more frequent status bar updates with more info. Unfortunately, this causes lag. // Would be cool to do more frequent status bar updates with more info. Unfortunately, this causes lag.

View File

@ -34,7 +34,11 @@ class CWorldEditor;
class CWorldEditor : public INodeEditor class CWorldEditor : public INodeEditor
{ {
Q_OBJECT Q_OBJECT
static const int mskMaxRecentProjects = 10;
Ui::CWorldEditor *ui; Ui::CWorldEditor *ui;
QMenu *mpOpenRecentMenu;
QAction *mRecentProjectsActions[ mskMaxRecentProjects ];
TResPtr<CWorld> mpWorld; TResPtr<CWorld> mpWorld;
TResPtr<CGameArea> mpArea; TResPtr<CGameArea> mpArea;
@ -55,6 +59,7 @@ public:
explicit CWorldEditor(QWidget *parent = 0); explicit CWorldEditor(QWidget *parent = 0);
~CWorldEditor(); ~CWorldEditor();
void closeEvent(QCloseEvent *pEvent); void closeEvent(QCloseEvent *pEvent);
bool CloseWorld();
void SetArea(CWorld *pWorld, CGameArea *pArea); void SetArea(CWorld *pWorld, CGameArea *pArea);
bool CheckUnsavedChanges(); bool CheckUnsavedChanges();
bool HasAnyScriptNodesSelected() const; bool HasAnyScriptNodesSelected() const;
@ -76,8 +81,14 @@ public slots:
void Cut(); void Cut();
void Copy(); void Copy();
void Paste(); void Paste();
void OpenProject();
void OpenRecentProject();
void CloseProject();
bool Save(); bool Save();
bool SaveAndRepack(); bool SaveAndRepack();
void OnActiveProjectChanged(CGameProject *pProj);
void OnLinksModified(const QList<CScriptObject*>& rkInstances); void OnLinksModified(const QList<CScriptObject*>& rkInstances);
void OnPropertyModified(IProperty *pProp); void OnPropertyModified(IProperty *pProp);
void SetSelectionActive(bool Active); void SetSelectionActive(bool Active);
@ -85,6 +96,7 @@ public slots:
void SetSelectionLayer(CScriptLayer *pLayer); void SetSelectionLayer(CScriptLayer *pLayer);
void DeleteSelection(); void DeleteSelection();
void UpdateOpenRecentActions();
void UpdateStatusBar(); void UpdateStatusBar();
void UpdateGizmoUI(); void UpdateGizmoUI();
void UpdateSelectionUI(); void UpdateSelectionUI();

View File

@ -415,8 +415,16 @@
<property name="title"> <property name="title">
<string>File</string> <string>File</string>
</property> </property>
<addaction name="ActionOpenProject"/>
<addaction name="ActionOpenRecent"/>
<addaction name="separator"/>
<addaction name="ActionSave"/> <addaction name="ActionSave"/>
<addaction name="ActionSaveAndRepack"/> <addaction name="ActionSaveAndRepack"/>
<addaction name="separator"/>
<addaction name="ActionExportGame"/>
<addaction name="separator"/>
<addaction name="ActionCloseProject"/>
<addaction name="ActionExit"/>
</widget> </widget>
<widget class="QMenu" name="menuEdit"> <widget class="QMenu" name="menuEdit">
<property name="title"> <property name="title">
@ -478,26 +486,13 @@
<addaction name="menuTools"/> <addaction name="menuTools"/>
<addaction name="menuView"/> <addaction name="menuView"/>
</widget> </widget>
<action name="ActionOpen">
<property name="text">
<string>Open</string>
</property>
</action>
<action name="ActionSave"> <action name="ActionSave">
<property name="icon"> <property name="icon">
<iconset resource="../Icons.qrc"> <iconset resource="../Icons.qrc">
<normaloff>:/icons/Save.png</normaloff>:/icons/Save.png</iconset> <normaloff>:/icons/Save.png</normaloff>:/icons/Save.png</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Save</string> <string>Save World</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="actionOpen_model_viewer">
<property name="text">
<string>Open Model Viewer</string>
</property> </property>
</action> </action>
<action name="ActionLink"> <action name="ActionLink">
@ -814,15 +809,48 @@
<property name="toolTip"> <property name="toolTip">
<string>Save and Repack</string> <string>Save and Repack</string>
</property> </property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
</property>
</action> </action>
<action name="ActionCollisionRenderSettings"> <action name="ActionCollisionRenderSettings">
<property name="text"> <property name="text">
<string>Collision Render Settings</string> <string>Collision Render Settings</string>
</property> </property>
</action> </action>
<action name="ActionOpenRecent">
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/Open_16px.png</normaloff>:/icons/Open_16px.png</iconset>
</property>
<property name="text">
<string>Open Recent</string>
</property>
</action>
<action name="ActionOpenProject">
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/Open_16px.png</normaloff>:/icons/Open_16px.png</iconset>
</property>
<property name="text">
<string>Open Project</string>
</property>
</action>
<action name="ActionExportGame">
<property name="text">
<string>Export Game</string>
</property>
</action>
<action name="ActionExit">
<property name="text">
<string>Exit</string>
</property>
</action>
<action name="ActionCloseProject">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Close Project</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -25,6 +25,9 @@ int main(int argc, char *argv[])
// Create application // Create application
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
CEditorApplication App(argc, argv); CEditorApplication App(argc, argv);
App.setApplicationName( APP_NAME );
App.setApplicationVersion( APP_VERSION );
App.setOrganizationName("Aruki");
App.setWindowIcon(QIcon(":/icons/AppIcon.ico")); App.setWindowIcon(QIcon(":/icons/AppIcon.ico"));
// Init log // Init log