Fixed various bugs and crashes and moved more functionality into the world editor
This commit is contained in:
parent
00a48e69f8
commit
c5de322ac7
|
@ -22,7 +22,7 @@ void main()
|
|||
const float kMaxDepth = 75.0; // Controls the max depth range that kDepthTintNear and kDepthTintFar are interpolated between
|
||||
const float kDepthTintNear = 0.0; // Sets the pixel color offset for pixels close to the screen
|
||||
const float kDepthTintFar = -0.2; // Sets the pixel color offset for pixels far from the screen
|
||||
const float kDepthCurveFactor = 2; // Controls the strength of the interpolation curve (higher = color chabges faster from up close and slower from further away)
|
||||
const float kDepthCurveFactor = 2; // Controls the strength of the interpolation curve (higher = color changes faster from up close and slower from further away)
|
||||
|
||||
// Apply some fake fog so pixels closer to the camera appear slightly brighter
|
||||
float Depth = ( (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) / (gl_DepthRange.far - gl_DepthRange.near) ) / gl_FragCoord.w;
|
||||
|
|
|
@ -356,6 +356,7 @@ CResource* CResourceEntry::LoadCooked(IInputStream& rInput)
|
|||
bool CResourceEntry::Unload()
|
||||
{
|
||||
ASSERT(mpResource != nullptr);
|
||||
ASSERT(!mpResource->IsReferenced());
|
||||
delete mpResource;
|
||||
mpResource = nullptr;
|
||||
return true;
|
||||
|
|
|
@ -277,6 +277,21 @@ void CResourceStore::CloseProject()
|
|||
// various TResPtrs are destroyed. There might be a cleaner solution than this.)
|
||||
DestroyUnreferencedResources();
|
||||
|
||||
// There should be no loaded resources!!!
|
||||
// If there are, that means something didn't clean up resource references properly on project close!!!
|
||||
if (!mLoadedResources.empty())
|
||||
{
|
||||
Log::Error(TString::FromInt32(mLoadedResources.size(), 0, 10) + " resources still loaded on project close:");
|
||||
|
||||
for (auto Iter = mLoadedResources.begin(); Iter != mLoadedResources.end(); Iter++)
|
||||
{
|
||||
CResourceEntry *pEntry = Iter->second;
|
||||
Log::Write("\t" + pEntry->Name().ToUTF8() + "." + pEntry->CookedExtension().ToString());
|
||||
}
|
||||
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
// Delete all entries from old project
|
||||
auto It = mResourceEntries.begin();
|
||||
|
||||
|
@ -286,16 +301,6 @@ void CResourceStore::CloseProject()
|
|||
|
||||
if (!pEntry->IsTransient())
|
||||
{
|
||||
if (pEntry->IsLoaded())
|
||||
{
|
||||
bool UnloadSuccess = pEntry->Unload();
|
||||
ASSERT(UnloadSuccess);
|
||||
|
||||
auto LoadIt = mLoadedResources.find(pEntry->ID());
|
||||
ASSERT(LoadIt != mLoadedResources.end());
|
||||
mLoadedResources.erase(LoadIt);
|
||||
}
|
||||
|
||||
delete pEntry;
|
||||
It = mResourceEntries.erase(It);
|
||||
}
|
||||
|
|
|
@ -172,12 +172,13 @@ void CScene::DeleteNode(CSceneNode *pNode)
|
|||
mNumNodes--;
|
||||
}
|
||||
|
||||
void CScene::SetActiveArea(CGameArea *pArea)
|
||||
void CScene::SetActiveArea(CWorld *pWorld, CGameArea *pArea)
|
||||
{
|
||||
// Clear existing area
|
||||
ClearScene();
|
||||
|
||||
// Create nodes for new area
|
||||
mpWorld = pWorld;
|
||||
mpArea = pArea;
|
||||
mpAreaRootNode = new CRootNode(this, -1, mpSceneRootNode);
|
||||
|
||||
|
@ -248,11 +249,6 @@ void CScene::SetActiveArea(CGameArea *pArea)
|
|||
Log::Write( TString::FromInt32(CSceneNode::NumNodes(), 0, 10) + " nodes" );
|
||||
}
|
||||
|
||||
void CScene::SetActiveWorld(CWorld* pWorld)
|
||||
{
|
||||
mpWorld = pWorld;
|
||||
}
|
||||
|
||||
void CScene::PostLoad()
|
||||
{
|
||||
mpSceneRootNode->OnLoadFinished();
|
||||
|
@ -265,6 +261,7 @@ void CScene::ClearScene()
|
|||
{
|
||||
mpAreaRootNode->Unparent();
|
||||
delete mpAreaRootNode;
|
||||
mpAreaRootNode = nullptr;
|
||||
}
|
||||
|
||||
mNodes.clear();
|
||||
|
@ -274,6 +271,7 @@ void CScene::ClearScene()
|
|||
mNumNodes = 0;
|
||||
|
||||
mpArea = nullptr;
|
||||
mpWorld = nullptr;
|
||||
}
|
||||
|
||||
void CScene::AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo)
|
||||
|
|
|
@ -56,8 +56,7 @@ public:
|
|||
CScriptNode* CreateScriptNode(CScriptObject *pObj, u32 NodeID = -1);
|
||||
CLightNode* CreateLightNode(CLight *pLight, u32 NodeID = -1);
|
||||
void DeleteNode(CSceneNode *pNode);
|
||||
void SetActiveArea(CGameArea *pArea);
|
||||
void SetActiveWorld(CWorld *pWorld);
|
||||
void SetActiveArea(CWorld *pWorld, CGameArea *pArea);
|
||||
void PostLoad();
|
||||
void ClearScene();
|
||||
void AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo);
|
||||
|
|
|
@ -16,11 +16,6 @@ CProjectOverviewDialog::CProjectOverviewDialog(QWidget *pParent)
|
|||
{
|
||||
mpUI->setupUi(this);
|
||||
|
||||
connect(mpUI->OpenProjectButton, SIGNAL(clicked()), this, SLOT(OpenProject()));
|
||||
connect(mpUI->ExportGameButton, SIGNAL(clicked()), this, SLOT(ExportGame()));
|
||||
connect(mpUI->LoadWorldButton, SIGNAL(clicked()), this, SLOT(LoadWorld()));
|
||||
connect(mpUI->LaunchEditorButton, SIGNAL(clicked()), this, SLOT(LaunchEditor()));
|
||||
connect(mpUI->ViewResourcesButton, SIGNAL(clicked()), this, SLOT(LaunchResourceBrowser()));
|
||||
connect(mpUI->CookPackageButton, SIGNAL(clicked()), this, SLOT(CookPackage()));
|
||||
connect(mpUI->CookAllDirtyPackagesButton, SIGNAL(clicked(bool)), this, SLOT(CookAllDirtyPackages()));
|
||||
|
||||
|
@ -36,59 +31,13 @@ CProjectOverviewDialog::~CProjectOverviewDialog()
|
|||
void CProjectOverviewDialog::ActiveProjectChanged(CGameProject *pProj)
|
||||
{
|
||||
mpProject = pProj;
|
||||
SetupWorldsList();
|
||||
SetupPackagesList();
|
||||
}
|
||||
|
||||
void CProjectOverviewDialog::ExportGame()
|
||||
{
|
||||
QString IsoPath = UICommon::OpenFileDialog(this, "Select ISO", "*.iso *.gcm *.tgc *.wbfs");
|
||||
if (IsoPath.isEmpty()) return;
|
||||
|
||||
QString ExportDir = UICommon::OpenDirDialog(this, "Select output export directory");
|
||||
if (ExportDir.isEmpty()) return;
|
||||
|
||||
CExportGameDialog ExportDialog(IsoPath, ExportDir, this);
|
||||
if (ExportDialog.HasValidDisc()) ExportDialog.exec();
|
||||
|
||||
if (ExportDialog.ExportSucceeded())
|
||||
{
|
||||
int OpenChoice = QMessageBox::information(this, "Export complete", "Export finished successfully! Open new project?", QMessageBox::Yes, QMessageBox::No);
|
||||
|
||||
if (OpenChoice == QMessageBox::Yes)
|
||||
gpEdApp->OpenProject(ExportDialog.ProjectPath());
|
||||
}
|
||||
}
|
||||
|
||||
void CProjectOverviewDialog::SetupWorldsList()
|
||||
{
|
||||
std::list<CAssetID> WorldIDs;
|
||||
mpProject->GetWorldList(WorldIDs);
|
||||
mWorldEntries.clear();
|
||||
mpUI->WorldsList->clear();
|
||||
|
||||
for (auto It = WorldIDs.begin(); It != WorldIDs.end(); It++)
|
||||
{
|
||||
CAssetID ID = *It;
|
||||
CResourceEntry *pEntry = gpResourceStore->FindEntry(ID);
|
||||
|
||||
if (!pEntry)
|
||||
{
|
||||
Log::Error("Couldn't find entry for world: " + ID.ToString());
|
||||
continue;
|
||||
}
|
||||
|
||||
mWorldEntries << pEntry;
|
||||
mpUI->WorldsList->addItem(TO_QSTRING(pEntry->Name()));
|
||||
}
|
||||
|
||||
mpUI->AreasGroupBox->setEnabled(false);
|
||||
mpUI->LoadWorldButton->setEnabled(!mWorldEntries.isEmpty());
|
||||
}
|
||||
|
||||
void CProjectOverviewDialog::SetupPackagesList()
|
||||
{
|
||||
mpUI->PackagesList->clear();
|
||||
if (!mpProject) return;
|
||||
|
||||
for (u32 iPkg = 0; iPkg < mpProject->NumPackages(); iPkg++)
|
||||
{
|
||||
|
@ -101,63 +50,6 @@ void CProjectOverviewDialog::SetupPackagesList()
|
|||
}
|
||||
}
|
||||
|
||||
void CProjectOverviewDialog::LoadWorld()
|
||||
{
|
||||
// Find world
|
||||
u32 WorldIdx = mpUI->WorldsList->currentRow();
|
||||
CResourceEntry *pWorldEntry = mWorldEntries[WorldIdx];
|
||||
mpWorld = pWorldEntry->Load();
|
||||
|
||||
mAreaEntries.clear();
|
||||
mpUI->AreaComboBox->clear();
|
||||
|
||||
if (mpWorld)
|
||||
{
|
||||
for (u32 iArea = 0; iArea < mpWorld->NumAreas(); iArea++)
|
||||
{
|
||||
CResourceEntry *pAreaEntry = gpResourceStore->FindEntry( mpWorld->AreaResourceID(iArea) );
|
||||
|
||||
if (pAreaEntry)
|
||||
{
|
||||
mAreaEntries << pAreaEntry;
|
||||
mpUI->AreaComboBox->addItem(TO_QSTRING(pAreaEntry->Name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mpUI->AreasGroupBox->setEnabled(true);
|
||||
mpUI->AreaComboBox->setEnabled(!mAreaEntries.isEmpty());
|
||||
mpUI->LaunchEditorButton->setEnabled(!mAreaEntries.isEmpty());
|
||||
gpResourceStore->DestroyUnreferencedResources();
|
||||
}
|
||||
|
||||
void CProjectOverviewDialog::LaunchEditor()
|
||||
{
|
||||
// Load area
|
||||
u32 AreaIdx = mpUI->AreaComboBox->currentIndex();
|
||||
CResourceEntry *pAreaEntry = mAreaEntries[AreaIdx];
|
||||
CGameArea *pArea = (CGameArea*) pAreaEntry->Load();
|
||||
|
||||
if (pArea)
|
||||
{
|
||||
pArea->SetWorldIndex(AreaIdx);
|
||||
mpWorld->SetAreaLayerInfo(pArea);
|
||||
gpEdApp->WorldEditor()->SetArea(mpWorld, AreaIdx);
|
||||
gpEdApp->WorldEditor()->showMaximized();
|
||||
}
|
||||
|
||||
else
|
||||
Log::Error("Failed to load area");
|
||||
|
||||
gpResourceStore->DestroyUnreferencedResources();
|
||||
}
|
||||
|
||||
void CProjectOverviewDialog::LaunchResourceBrowser()
|
||||
{
|
||||
gpEdApp->ResourceBrowser()->show();
|
||||
gpEdApp->ResourceBrowser()->raise();
|
||||
}
|
||||
|
||||
void CProjectOverviewDialog::CookPackage()
|
||||
{
|
||||
u32 PackageIdx = mpUI->PackagesList->currentRow();
|
||||
|
|
|
@ -26,15 +26,9 @@ public:
|
|||
|
||||
public slots:
|
||||
void ActiveProjectChanged(CGameProject *pProj);
|
||||
void ExportGame();
|
||||
void LoadWorld();
|
||||
void LaunchEditor();
|
||||
void LaunchResourceBrowser();
|
||||
void SetupPackagesList();
|
||||
void CookPackage();
|
||||
void CookAllDirtyPackages();
|
||||
|
||||
void SetupWorldsList();
|
||||
void SetupPackagesList();
|
||||
};
|
||||
|
||||
#endif // CPROJECTOVERVIEWDIALOG_H
|
||||
|
|
|
@ -12,7 +12,7 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
|||
: QDialog(pParent)
|
||||
, mpUI(new Ui::CResourceBrowser)
|
||||
, mpSelectedEntry(nullptr)
|
||||
, mpStore(gpResourceStore)
|
||||
, mpStore(nullptr)
|
||||
, mpSelectedDir(nullptr)
|
||||
, mAssetListMode(true)
|
||||
, mSearching(false)
|
||||
|
@ -232,7 +232,10 @@ void CResourceBrowser::UpdateDescriptionLabel()
|
|||
void CResourceBrowser::UpdateStore()
|
||||
{
|
||||
int StoreIndex = mpUI->StoreComboBox->currentIndex();
|
||||
CResourceStore *pNewStore = (StoreIndex == 0 ? gpResourceStore : gpEditorStore);
|
||||
|
||||
CGameProject *pProj = gpEdApp->ActiveProject();
|
||||
CResourceStore *pProjStore = (pProj ? pProj->ResourceStore() : nullptr);
|
||||
CResourceStore *pNewStore = (StoreIndex == 0 ? pProjStore : gpEditorStore);
|
||||
|
||||
if (mpStore != pNewStore)
|
||||
{
|
||||
|
|
|
@ -53,6 +53,11 @@ CResourceSelector::CResourceSelector(QWidget *pParent /*= 0*/)
|
|||
mpLayout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(mpLayout);
|
||||
|
||||
// Font
|
||||
QFont Font = font();
|
||||
Font.setPointSize(10);
|
||||
setFont(Font);
|
||||
|
||||
// UI Connections
|
||||
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(CreateContextMenu(QPoint)));
|
||||
connect(mpSetButton, SIGNAL(clicked()), this, SLOT(Set()));
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "WInstancesTab.h"
|
||||
|
||||
#include "Editor/CBasicViewport.h"
|
||||
#include "Editor/CExportGameDialog.h"
|
||||
#include "Editor/CNodeCopyMimeData.h"
|
||||
#include "Editor/CPakToolDialog.h"
|
||||
#include "Editor/CSelectionIterator.h"
|
||||
|
@ -53,7 +54,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
|||
ui->splitter->setSizes(SplitterSizes);
|
||||
|
||||
// Initialize UI stuff
|
||||
ui->MainViewport->Camera().Snap(CVector3f(0.f, 5.f, 1.f));
|
||||
ResetCamera();
|
||||
ui->MainViewport->SetScene(this, &mScene);
|
||||
ui->MainViewport->setAcceptDrops(true);
|
||||
ui->TransformSpinBox->SetOrientation(Qt::Horizontal);
|
||||
|
@ -110,6 +111,26 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
|||
|
||||
mpCollisionDialog = new CCollisionRenderSettingsDialog(this, this);
|
||||
|
||||
// Resource Browser button
|
||||
QPushButton *pBrowserButton = new QPushButton(this);
|
||||
pBrowserButton->setText("Resource Browser");
|
||||
connect(pBrowserButton, SIGNAL(pressed()), this, SLOT(OpenResourceBrowser()));
|
||||
|
||||
QPalette Palette = pBrowserButton->palette();
|
||||
QBrush ButtonBrush = Palette.button();
|
||||
ButtonBrush.setColor( QColor(36, 100, 100) );
|
||||
Palette.setBrush(QPalette::Button, ButtonBrush);
|
||||
pBrowserButton->setPalette(Palette);
|
||||
|
||||
QFont BrowserButtonFont = pBrowserButton->font();
|
||||
BrowserButtonFont.setPointSize( BrowserButtonFont.pointSize() + 3 );
|
||||
pBrowserButton->setFont(BrowserButtonFont);
|
||||
|
||||
QWidget *pSpacerWidget = new QWidget(this);
|
||||
pSpacerWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
ui->MainToolBar->addWidget(pSpacerWidget);
|
||||
ui->MainToolBar->addWidget(pBrowserButton);
|
||||
|
||||
// "Open Recent" menu
|
||||
mpOpenRecentMenu = new QMenu(this);
|
||||
ui->ActionOpenRecent->setMenu(mpOpenRecentMenu);
|
||||
|
@ -149,6 +170,10 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
|||
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->ActionExportGame, SIGNAL(triggered()), this, SLOT(ExportGame()));
|
||||
connect(ui->ActionCloseProject, SIGNAL(triggered()), this, SLOT(CloseProject()));
|
||||
connect(ui->ActionExit, SIGNAL(triggered()), this, SLOT(close()));
|
||||
|
||||
connect(ui->ActionCut, SIGNAL(triggered()), this, SLOT(Cut()));
|
||||
connect(ui->ActionCopy, SIGNAL(triggered()), this, SLOT(Copy()));
|
||||
connect(ui->ActionPaste, SIGNAL(triggered()), this, SLOT(Paste()));
|
||||
|
@ -216,6 +241,7 @@ bool CWorldEditor::CloseWorld()
|
|||
ExitPickMode();
|
||||
ClearSelection();
|
||||
ui->MainViewport->ResetHover();
|
||||
mScene.ClearScene();
|
||||
|
||||
mUndoStack.clear();
|
||||
mpCollisionDialog->close();
|
||||
|
@ -262,9 +288,7 @@ bool CWorldEditor::SetArea(CWorld *pWorld, int AreaIndex)
|
|||
mpArea = pAreaEntry->Load();
|
||||
ASSERT(mpArea);
|
||||
mpWorld->SetAreaLayerInfo(mpArea);
|
||||
|
||||
mScene.SetActiveWorld(mpWorld);
|
||||
mScene.SetActiveArea(mpArea);
|
||||
mScene.SetActiveArea(mpWorld, mpArea);
|
||||
|
||||
// Snap camera to new area
|
||||
CCamera *pCamera = &ui->MainViewport->Camera();
|
||||
|
@ -353,6 +377,11 @@ bool CWorldEditor::CheckUnsavedChanges()
|
|||
return OkToClear;
|
||||
}
|
||||
|
||||
void CWorldEditor::ResetCamera()
|
||||
{
|
||||
ui->MainViewport->Camera().Snap(CVector3f(0.f, 5.f, 1.f));
|
||||
}
|
||||
|
||||
bool CWorldEditor::HasAnyScriptNodesSelected() const
|
||||
{
|
||||
for (CSelectionIterator It(mpSelection); It; ++It)
|
||||
|
@ -446,11 +475,6 @@ void CWorldEditor::OpenRecentProject()
|
|||
}
|
||||
}
|
||||
|
||||
void CWorldEditor::CloseProject()
|
||||
{
|
||||
gpEdApp->CloseProject();
|
||||
}
|
||||
|
||||
bool CWorldEditor::Save()
|
||||
{
|
||||
if (!mpArea)
|
||||
|
@ -483,6 +507,31 @@ bool CWorldEditor::SaveAndRepack()
|
|||
return true;
|
||||
}
|
||||
|
||||
void CWorldEditor::ExportGame()
|
||||
{
|
||||
QString IsoPath = UICommon::OpenFileDialog(this, "Select ISO", "*.iso *.gcm *.tgc *.wbfs");
|
||||
if (IsoPath.isEmpty()) return;
|
||||
|
||||
QString ExportDir = UICommon::OpenDirDialog(this, "Select output export directory");
|
||||
if (ExportDir.isEmpty()) return;
|
||||
|
||||
CExportGameDialog ExportDialog(IsoPath, ExportDir, this);
|
||||
if (ExportDialog.HasValidDisc()) ExportDialog.exec();
|
||||
|
||||
if (ExportDialog.ExportSucceeded())
|
||||
{
|
||||
int OpenChoice = QMessageBox::information(this, "Export complete", "Export finished successfully! Open new project?", QMessageBox::Yes, QMessageBox::No);
|
||||
|
||||
if (OpenChoice == QMessageBox::Yes)
|
||||
gpEdApp->OpenProject(ExportDialog.ProjectPath());
|
||||
}
|
||||
}
|
||||
|
||||
void CWorldEditor:: CloseProject()
|
||||
{
|
||||
gpEdApp->CloseProject();
|
||||
}
|
||||
|
||||
void CWorldEditor::ChangeEditMode(int Mode)
|
||||
{
|
||||
// This function is connected to the edit mode QButtonGroup.
|
||||
|
@ -521,6 +570,7 @@ void CWorldEditor::OpenResourceBrowser()
|
|||
void CWorldEditor::OnActiveProjectChanged(CGameProject *pProj)
|
||||
{
|
||||
ui->ActionCloseProject->setEnabled( pProj != nullptr );
|
||||
ResetCamera();
|
||||
if (!pProj) return;
|
||||
|
||||
// Update recent projects list
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
bool CloseWorld();
|
||||
bool SetArea(CWorld *pWorld, int AreaIndex);
|
||||
bool CheckUnsavedChanges();
|
||||
void ResetCamera();
|
||||
bool HasAnyScriptNodesSelected() const;
|
||||
|
||||
inline CWorld* ActiveWorld() const { return mpWorld; }
|
||||
|
@ -101,9 +102,10 @@ public slots:
|
|||
|
||||
void OpenProject();
|
||||
void OpenRecentProject();
|
||||
void CloseProject();
|
||||
bool Save();
|
||||
bool SaveAndRepack();
|
||||
void ExportGame();
|
||||
void CloseProject();
|
||||
|
||||
void ChangeEditMode(int Mode);
|
||||
void ChangeEditMode(EWorldEditorMode Mode);
|
||||
|
|
|
@ -57,6 +57,8 @@ void CWorldInfoSidebar::OnActiveProjectChanged(CGameProject *pProj)
|
|||
mpUI->ProjectInfoWidget->setHidden( pProj == nullptr );
|
||||
mpUI->WorldInfoWidget->setHidden(true);
|
||||
mpUI->AreaInfoWidget->setHidden(true);
|
||||
mpUI->AreaSearchLineEdit->clear();
|
||||
mProxyModel.SetFilterString("");
|
||||
|
||||
bool IsEchoes = pProj && (pProj->Game() == eEchoesDemo || pProj->Game() == eEchoes);
|
||||
mpUI->GameNameLabel->setText( pProj ? TO_QSTRING(pProj->Name()) : "" );
|
||||
|
|
|
@ -231,7 +231,13 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="AreaNameLineEdit"/>
|
||||
<widget class="QLineEdit" name="AreaNameLineEdit">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="AreaLabel">
|
||||
|
|
Loading…
Reference in New Issue