Initial commit of current work on Prime World Editor

This commit is contained in:
parax0
2015-07-26 17:39:49 -04:00
commit 66e8c2ebcb
305 changed files with 33469 additions and 0 deletions

5
UI/CDarkStyle.cpp Normal file
View File

@@ -0,0 +1,5 @@
#include "CDarkStyle.h"
CDarkStyle::CDarkStyle()
{
}

14
UI/CDarkStyle.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef CDARKSTYLE_H
#define CDARKSTYLE_H
#include <QProxyStyle>
class CDarkStyle : public QProxyStyle
{
Q_OBJECT
public:
CDarkStyle();
};
#endif // CDARKSTYLE_H

247
UI/CEditorGLWidget.cpp Normal file
View File

@@ -0,0 +1,247 @@
#include <GL/glew.h>
#include <gtc/matrix_transform.hpp>
#include <gtx/transform.hpp>
#include <Core/CGraphics.h>
#include <Core/CRenderer.h>
#include <QTimer>
#include "CEditorGLWidget.h"
#include <iostream>
#include <Core/CGraphics.h>
#include <Resource/factory/CTextureDecoder.h>
#include <Common/CTimer.h>
#include <Common/CVector4f.h>
#include <QOpenGLContext>
#include <QPainter>
#include <QOpenGLPaintDevice>
QTimer CEditorGLWidget::sRefreshTimer;
CEditorGLWidget::CEditorGLWidget(QWidget *pParent) :
QOpenGLWidget(pParent)
{
setMouseTracking(true);
mLastDrawTime = CTimer::GlobalTime();
mKeysPressed = 0;
mButtonsPressed = 0;
mCursorState = Qt::ArrowCursor;
mCursorVisible = true;
mCamera.SetAspectRatio((float) width() / height());
connect(&sRefreshTimer, SIGNAL(timeout()), this, SLOT(update()));
if (!sRefreshTimer.isActive())
sRefreshTimer.start(0);
}
CEditorGLWidget::~CEditorGLWidget()
{
}
void CEditorGLWidget::initializeGL()
{
// Initialize CGraphics
CGraphics::Initialize();
// Setting various GL flags
glEnable(GL_DEPTH_TEST);
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(0xFFFF);
glDepthFunc(GL_LEQUAL);
glEnable(GL_BLEND);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.f, 5.f);
// Clear cached material
CMaterial::KillCachedMaterial();
CShader::KillCachedShader();
// Initialize renderer
emit ViewportResized(width(), height());
}
void CEditorGLWidget::paintGL()
{
double DeltaTime = CTimer::GlobalTime() - mLastDrawTime;
mLastDrawTime = CTimer::GlobalTime();
// Camera movement is processed here in order to sync it with the paint event
// This way movement happens exactly once per frame - no more, no less
ProcessInput(DeltaTime);
mCamera.LoadMatrices();
// Pre-render signal allows for per-frame operations to be performed before the draw happens
emit PreRender();
// We emit a signal to indicate it's time to render the viewport instead of doing the rendering here.
// This allows the editor GL widget class to be reused among multiple editors with different rendering needs.
emit Render(mCamera);
// Post-render signal allows for the frame to be completed with post-processing
emit PostRender();
}
void CEditorGLWidget::resizeGL(int w, int h)
{
mCamera.SetAspectRatio((float) w / h);
glViewport(0, 0, w, h);
emit ViewportResized(w, h);
}
void CEditorGLWidget::mouseMoveEvent(QMouseEvent *pEvent)
{
if ((!IsMouseInputActive()) && (mButtonsPressed & eLeftButton))
emit MouseDrag(pEvent);
}
void CEditorGLWidget::mousePressEvent(QMouseEvent *pEvent)
{
setFocus();
if (pEvent->button() == Qt::MidButton) mButtonsPressed |= eMiddleButton;
if (pEvent->button() == Qt::RightButton) mButtonsPressed |= eRightButton;
if (IsMouseInputActive())
SetCursorVisible(false);
// Left click only activates if mouse input is inactive to prevent the user from
// clicking on things and creating selection rectangles while the cursor is hidden
else if (pEvent->button() == Qt::LeftButton)
mButtonsPressed |= eLeftButton;
mLastMousePos = pEvent->globalPos();
}
void CEditorGLWidget::mouseReleaseEvent(QMouseEvent *pEvent)
{
if (pEvent->button() == Qt::LeftButton) mButtonsPressed &= ~eLeftButton;
if (pEvent->button() == Qt::MidButton) mButtonsPressed &= ~eMiddleButton;
if (pEvent->button() == Qt::RightButton) mButtonsPressed &= ~eRightButton;
// Make cursor visible and emit mouse click event if middle/right mouse buttons are both released
if (!IsMouseInputActive())
{
SetCursorVisible(true);
emit MouseClick(pEvent);
}
}
void CEditorGLWidget::keyPressEvent(QKeyEvent *pEvent)
{
switch (pEvent->key())
{
case Qt::Key_Q: mKeysPressed |= eQKey; break;
case Qt::Key_W: mKeysPressed |= eWKey; break;
case Qt::Key_E: mKeysPressed |= eEKey; break;
case Qt::Key_A: mKeysPressed |= eAKey; break;
case Qt::Key_S: mKeysPressed |= eSKey; break;
case Qt::Key_D: mKeysPressed |= eDKey; break;
case Qt::Key_Control: mKeysPressed |= eCtrlKey; break;
}
}
void CEditorGLWidget::keyReleaseEvent(QKeyEvent *pEvent)
{
switch (pEvent->key())
{
case Qt::Key_Q: mKeysPressed &= ~eQKey; break;
case Qt::Key_W: mKeysPressed &= ~eWKey; break;
case Qt::Key_E: mKeysPressed &= ~eEKey; break;
case Qt::Key_A: mKeysPressed &= ~eAKey; break;
case Qt::Key_S: mKeysPressed &= ~eSKey; break;
case Qt::Key_D: mKeysPressed &= ~eDKey; break;
case Qt::Key_Control: mKeysPressed &= ~eCtrlKey; break;
}
}
void CEditorGLWidget::wheelEvent(QWheelEvent *pEvent)
{
// Maybe track a "wheel delta" member variable and let CCamera decide what to do with it?
mCamera.Zoom(pEvent->angleDelta().y() / 6000.f);
}
void CEditorGLWidget::focusOutEvent(QFocusEvent*)
{
// When the widget loses focus, release all input.
mButtonsPressed = 0;
mKeysPressed = 0;
SetCursorVisible(true);
}
void CEditorGLWidget::SetCursorState(const QCursor &Cursor)
{
mCursorState = Cursor;
if (IsCursorVisible())
setCursor(Cursor);
}
void CEditorGLWidget::SetCursorVisible(bool visible)
{
mCursorVisible = visible;
if (visible)
setCursor(mCursorState);
else
setCursor(Qt::BlankCursor);
}
bool CEditorGLWidget::IsCursorVisible()
{
return mCursorVisible;
}
bool CEditorGLWidget::IsMouseInputActive()
{
static const int skMoveButtons = eMiddleButton | eRightButton;
return ((mButtonsPressed & skMoveButtons) != 0);
}
bool CEditorGLWidget::IsKeyboardInputActive()
{
static const int skMoveKeys = eQKey | eWKey | eEKey | eAKey | eSKey | eDKey;
return ((mKeysPressed & skMoveKeys) != 0);
}
CCamera& CEditorGLWidget::Camera()
{
return mCamera;
}
CRay CEditorGLWidget::CastRay()
{
CVector2f MouseCoords = MouseDeviceCoordinates();
return mCamera.CastRay(MouseCoords);
}
CVector2f CEditorGLWidget::MouseDeviceCoordinates()
{
QPoint MousePos = QCursor::pos();
QPoint ThisPos = this->mapToGlobal(pos());
MousePos -= ThisPos;
CVector2f Device(
(((2.f * MousePos.x()) / width()) - 1.f),
(1.f - ((2.f * MousePos.y()) / height()))
);
return Device;
}
// ************ PRIVATE ************
void CEditorGLWidget::ProcessInput(double DeltaTime)
{
if (IsMouseInputActive())
{
float XMovement = (QCursor::pos().x() - mLastMousePos.x()) * 0.01f;
float YMovement = (QCursor::pos().y() - mLastMousePos.y()) * 0.01f;
if ((XMovement != 0) || (YMovement != 0))
{
mCamera.ProcessMouseInput((EKeyInputs) mKeysPressed, (EMouseInputs) mButtonsPressed, XMovement, YMovement);
QCursor::setPos(mLastMousePos);
}
}
if (IsKeyboardInputActive())
mCamera.ProcessKeyInput((EKeyInputs) mKeysPressed, DeltaTime);
}

63
UI/CEditorGLWidget.h Normal file
View File

@@ -0,0 +1,63 @@
#ifndef CEDITORGLWIDGET_H
#define CEDITORGLWIDGET_H
#include <QTimer>
#include <gl/glew.h>
#include <QOpenGLWidget>
#include <QMouseEvent>
#include <Common/CVector2f.h>
#include <Common/CVector2i.h>
#include <Core/CSceneManager.h>
#include <Core/CRenderer.h>
#include <Resource/CFont.h>
#include <Common/CRay.h>
class CEditorGLWidget : public QOpenGLWidget
{
Q_OBJECT
static QTimer sRefreshTimer;
CCamera mCamera;
QPoint mLastMousePos;
double mLastDrawTime;
QPoint mLeftClickPoint;
int mButtonsPressed; // int container for EMouseInputs flags
int mKeysPressed; // int container for EKeyInputs flags
QCursor mCursorState;
bool mCursorVisible;
public:
explicit CEditorGLWidget(QWidget *pParent = 0);
~CEditorGLWidget();
void initializeGL();
void paintGL();
void resizeGL(int w, int h);
void mouseMoveEvent(QMouseEvent *pEvent);
void mousePressEvent(QMouseEvent *pEvent);
void mouseReleaseEvent(QMouseEvent *pEvent);
void keyPressEvent(QKeyEvent *pEvent);
void keyReleaseEvent(QKeyEvent *pEvent);
void wheelEvent(QWheelEvent *pEvent);
void focusOutEvent(QFocusEvent *pEvent);
void SetCursorState(const QCursor& Cursor);
void SetCursorVisible(bool visible);
bool IsCursorVisible();
bool IsMouseInputActive();
bool IsKeyboardInputActive();
CCamera& Camera();
CRay CastRay();
CVector2f MouseDeviceCoordinates();
signals:
void ViewportResized(int w, int h);
void PreRender();
void Render(CCamera& Camera);
void PostRender();
void MouseClick(QMouseEvent *pEvent);
void MouseDrag(QMouseEvent *pEvent);
private:
void ProcessInput(double DeltaTime);
};
#endif

14
UI/CMaterialEditor.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include "CMaterialEditor.h"
#include "ui_CMaterialEditor.h"
CMaterialEditor::CMaterialEditor(QWidget *parent) :
QDialog(parent),
ui(new Ui::CMaterialEditor)
{
ui->setupUi(this);
}
CMaterialEditor::~CMaterialEditor()
{
delete ui;
}

22
UI/CMaterialEditor.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef CMATERIALEDITOR_H
#define CMATERIALEDITOR_H
#include <QDialog>
namespace Ui {
class CMaterialEditor;
}
class CMaterialEditor : public QDialog
{
Q_OBJECT
public:
explicit CMaterialEditor(QWidget *parent = 0);
~CMaterialEditor();
private:
Ui::CMaterialEditor *ui;
};
#endif // CMATERIALEDITOR_H

18
UI/CMaterialEditor.ui Normal file
View File

@@ -0,0 +1,18 @@
<ui version="4.0">
<class>CMaterialEditor</class>
<widget class="QDialog" name="CMaterialEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
</widget>
<resources/>
<connections/>
</ui>

795
UI/CModelEditorWindow.cpp Normal file
View File

@@ -0,0 +1,795 @@
#include "CModelEditorWindow.h"
#include "ui_CModelEditorWindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include "WResourceSelector.h"
#include <Common/StringUtil.h>
#include <Core/CDrawUtil.h>
#include <Core/CRenderer.h>
#include <Core/CSceneManager.h>
#include <Resource/factory/CTextureDecoder.h>
#include <Resource/cooker/CModelCooker.h>
#include "WColorPicker.h"
#include <iostream>
#include <gtc/matrix_transform.hpp>
CModelEditorWindow::CModelEditorWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::CModelEditorWindow)
{
ui->setupUi(this);
mpScene = new CSceneManager();
mpCurrentMat = nullptr;
mpCurrentModel = nullptr;
mpCurrentModelNode = new CModelNode(mpScene);
mpCurrentPass = nullptr;
mIgnoreSignals = false;
mpRenderer = new CRenderer();
mpRenderer->ToggleGrid(true);
mpRenderer->SetClearColor(CColor(0.3f, 0.3f, 0.3f, 1.f));
CCamera& Camera = ui->PreviewGLWidget->Camera();
Camera.Snap(CVector3f(0, 3, 1));
Camera.SetFree();
Camera.SetMoveSpeed(0.5f);
mDrawMode = eDrawMesh;
// UI initialization
UpdateAnimParamUI(-1);
ui->IndTextureResSelector->SetResType(eTexture);
ui->IndTextureResSelector->SetPreviewPanelEnabled(true);
ui->PassTextureResSelector->SetResType(eTexture);
ui->PassTextureResSelector->SetPreviewPanelEnabled(true);
ui->PassTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
ui->PassTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
ui->ClearColorPicker->setColor(QColor(76, 76, 76, 255));
// Viewport Signal/Slot setup
connect(ui->PreviewGLWidget, SIGNAL(ViewportResized(int,int)), this, SLOT(SetViewportSize(int,int)));
connect(ui->PreviewGLWidget, SIGNAL(Render(CCamera&)), this, SLOT(PaintViewport(CCamera&)));
// Editor UI Signal/Slot setup
ui->SetSelectionComboBox->setProperty ("ModelEditorWidgetType", eSetSelectComboBox);
ui->MatSelectionComboBox->setProperty ("ModelEditorWidgetType", eMatSelectComboBox);
ui->EnableTransparencyCheck->setProperty ("ModelEditorWidgetType", eEnableTransparencyCheckBox);
ui->EnablePunchthroughCheck->setProperty ("ModelEditorWidgetType", eEnablePunchthroughCheckBox);
ui->EnableReflectionCheck->setProperty ("ModelEditorWidgetType", eEnableReflectionCheckBox);
ui->EnableSurfaceReflectionCheck->setProperty ("ModelEditorWidgetType", eEnableSurfaceReflectionCheckBox);
ui->EnableDepthWriteCheck->setProperty ("ModelEditorWidgetType", eEnableDepthWriteCheckBox);
ui->EnableOccluderCheck->setProperty ("ModelEditorWidgetType", eEnableOccluderCheckBox);
ui->EnableLightmapCheck->setProperty ("ModelEditorWidgetType", eEnableLightmapCheckBox);
ui->EnableDynamicLightingCheck->setProperty ("ModelEditorWidgetType", eEnableLightingCheckBox);
ui->SourceBlendComboBox->setProperty ("ModelEditorWidgetType", eSourceBlendComboBox);
ui->DestBlendComboBox->setProperty ("ModelEditorWidgetType", eDestBlendComboBox);
ui->KonstColorPickerA->setProperty ("ModelEditorWidgetType", eKonstColorPickerA);
ui->KonstColorPickerB->setProperty ("ModelEditorWidgetType", eKonstColorPickerB);
ui->KonstColorPickerC->setProperty ("ModelEditorWidgetType", eKonstColorPickerC);
ui->KonstColorPickerD->setProperty ("ModelEditorWidgetType", eKonstColorPickerD);
ui->IndTextureResSelector->setProperty ("ModelEditorWidgetType", eIndTextureResSelector);
ui->PassTable->setProperty ("ModelEditorWidgetType", ePassTableWidget);
ui->TevKColorSelComboBox->setProperty ("ModelEditorWidgetType", eTevKColorSelComboBox);
ui->TevKAlphaSelComboBox->setProperty ("ModelEditorWidgetType", eTevKAlphaSelComboBox);
ui->TevRasSelComboBox->setProperty ("ModelEditorWidgetType", eTevRasSelComboBox);
ui->TexCoordSrcComboBox->setProperty ("ModelEditorWidgetType", eTevTexSourceComboBox);
ui->PassTextureResSelector->setProperty ("ModelEditorWidgetType", ePassTextureResSelector);
ui->TevColor1ComboBox->setProperty ("ModelEditorWidgetType", eTevColorComboBoxA);
ui->TevColor2ComboBox->setProperty ("ModelEditorWidgetType", eTevColorComboBoxB);
ui->TevColor3ComboBox->setProperty ("ModelEditorWidgetType", eTevColorComboBoxC);
ui->TevColor4ComboBox->setProperty ("ModelEditorWidgetType", eTevColorComboBoxD);
ui->TevColorOutputComboBox->setProperty ("ModelEditorWidgetType", eTevColorOutputComboBox);
ui->TevAlpha1ComboBox->setProperty ("ModelEditorWidgetType", eTevAlphaComboBoxA);
ui->TevAlpha2ComboBox->setProperty ("ModelEditorWidgetType", eTevAlphaComboBoxB);
ui->TevAlpha3ComboBox->setProperty ("ModelEditorWidgetType", eTevAlphaComboBoxC);
ui->TevAlpha4ComboBox->setProperty ("ModelEditorWidgetType", eTevAlphaComboBoxD);
ui->TevAlphaOutputComboBox->setProperty ("ModelEditorWidgetType", eTevAlphaOutputComboBox);
ui->AnimTypeComboBox->setProperty ("ModelEditorWidgetType", eAnimModeComboBox);
ui->AnimParamASpinBox->setProperty ("ModelEditorWidgetType", eAnimParamASpinBox);
ui->AnimParamBSpinBox->setProperty ("ModelEditorWidgetType", eAnimParamBSpinBox);
ui->AnimParamCSpinBox->setProperty ("ModelEditorWidgetType", eAnimParamCSpinBox);
ui->AnimParamDSpinBox->setProperty ("ModelEditorWidgetType", eAnimParamDSpinBox);
connect(ui->SetSelectionComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateUI(int)));
connect(ui->MatSelectionComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateUI(int)));
connect(ui->EnableTransparencyCheck, SIGNAL(toggled(bool)), this, SLOT(UpdateMaterial(bool)));
connect(ui->EnablePunchthroughCheck, SIGNAL(toggled(bool)), this, SLOT(UpdateMaterial(bool)));
connect(ui->EnableReflectionCheck, SIGNAL(toggled(bool)), this, SLOT(UpdateMaterial(bool)));
connect(ui->EnableSurfaceReflectionCheck, SIGNAL(toggled(bool)), this, SLOT(UpdateMaterial(bool)));
connect(ui->EnableDepthWriteCheck, SIGNAL(toggled(bool)), this, SLOT(UpdateMaterial(bool)));
connect(ui->EnableOccluderCheck, SIGNAL(toggled(bool)), this, SLOT(UpdateMaterial(bool)));
connect(ui->EnableLightmapCheck, SIGNAL(toggled(bool)), this, SLOT(UpdateMaterial(bool)));
connect(ui->EnableDynamicLightingCheck, SIGNAL(toggled(bool)), this, SLOT(UpdateMaterial(bool)));
connect(ui->SourceBlendComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->DestBlendComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->KonstColorPickerA, SIGNAL(colorChanged(QColor)), this, SLOT(UpdateMaterial(QColor)));
connect(ui->KonstColorPickerB, SIGNAL(colorChanged(QColor)), this, SLOT(UpdateMaterial(QColor)));
connect(ui->KonstColorPickerC, SIGNAL(colorChanged(QColor)), this, SLOT(UpdateMaterial(QColor)));
connect(ui->KonstColorPickerD, SIGNAL(colorChanged(QColor)), this, SLOT(UpdateMaterial(QColor)));
connect(ui->PassTable, SIGNAL(cellClicked(int,int)), this, SLOT(UpdateMaterial(int, int)));
connect(ui->TevKColorSelComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevKAlphaSelComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevRasSelComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TexCoordSrcComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevColor1ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevColor2ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevColor3ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevColor4ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevColorOutputComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevAlpha1ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevAlpha2ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevAlpha3ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevAlpha4ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->TevAlphaOutputComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->AnimTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMaterial(int)));
connect(ui->AnimParamASpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateMaterial(double)));
connect(ui->AnimParamBSpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateMaterial(double)));
connect(ui->AnimParamCSpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateMaterial(double)));
connect(ui->AnimParamDSpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateMaterial(double)));
// That was fun
}
CModelEditorWindow::~CModelEditorWindow()
{
delete mpCurrentModelNode;
delete mpRenderer;
delete ui;
}
void CModelEditorWindow::SetActiveModel(CModel *pModel)
{
mpCurrentModelNode->SetModel(pModel);
mpCurrentModel = pModel;
mModelToken = CToken(pModel);
ui->MeshInfoLabel->setText(QString::number(pModel->GetVertexCount()) + " vertices, " + QString::number(pModel->GetTriangleCount()) + " triangles");
ui->MatInfoLabel->setText(QString::number(pModel->GetMatCount()) + " materials, " + QString::number(pModel->GetMatSetCount()) + " set" + (pModel->GetMatSetCount() == 1 ? "" : "s"));
// Set items in matset combo box
ui->SetSelectionComboBox->blockSignals(true);
ui->SetSelectionComboBox->clear();
for (u32 iSet = 0; iSet < pModel->GetMatSetCount(); iSet++)
ui->SetSelectionComboBox->addItem("Set #" + QString::number(iSet + 1));
ui->SetSelectionComboBox->setCurrentIndex(0);
ui->SetSelectionComboBox->blockSignals(false);
// Set items in mat combo box
ui->MatSelectionComboBox->blockSignals(true);
ui->MatSelectionComboBox->clear();
for (u32 iMat = 0; iMat < pModel->GetMatCount(); iMat++)
ui->MatSelectionComboBox->addItem("Material #" + QString::number(iMat + 1));
ui->MatSelectionComboBox->setCurrentIndex(0);
ui->MatSelectionComboBox->setEnabled( pModel->GetMatCount() > 1 );
ui->MatSelectionComboBox->blockSignals(false);
// Emit signals to set up UI
ui->SetSelectionComboBox->currentIndexChanged(0);
// Gray out set selection for models with one set
ui->SetSelectionComboBox->setEnabled( pModel->GetMatSetCount() > 1 );
ui->MatSelectionComboBox->setEnabled( pModel->GetMatCount() > 1 );
}
void CModelEditorWindow::SetActiveMaterial(int MatIndex)
{
if (!mpCurrentModel) return;
u32 SetIndex = ui->SetSelectionComboBox->currentIndex();
mpCurrentMat = mpCurrentModel->GetMaterialByIndex(SetIndex, MatIndex);
if (!mpCurrentMat) return;
//mpCurrentMat->SetTint(CColor(1.f, 0.5f, 0.5f, 1.f));
// Set up UI
CMaterial::EMaterialOptions Settings = mpCurrentMat->Options();
mIgnoreSignals = true;
ui->EnableTransparencyCheck->setChecked( Settings & CMaterial::eTransparent );
ui->EnablePunchthroughCheck->setChecked( Settings & CMaterial::ePunchthrough );
ui->EnableReflectionCheck->setChecked( Settings & CMaterial::eReflection );
ui->EnableSurfaceReflectionCheck->setChecked( Settings & CMaterial::eSurfaceReflection );
ui->EnableDepthWriteCheck->setChecked( Settings & CMaterial::eDepthWrite );
ui->EnableOccluderCheck->setChecked( Settings & CMaterial::eOccluder );
ui->EnableLightmapCheck->setChecked( Settings & CMaterial::eLightmap );
ui->EnableDynamicLightingCheck->setChecked( mpCurrentMat->IsLightingEnabled() );
u32 SrcFac = (u32) mpCurrentMat->BlendSrcFac();
u32 DstFac = (u32) mpCurrentMat->BlendDstFac();
if (SrcFac >= 0x300) SrcFac -= 0x2FE;
if (DstFac >= 0x300) DstFac -= 0x2FE;
ui->SourceBlendComboBox->setCurrentIndex(SrcFac);
ui->DestBlendComboBox->setCurrentIndex(DstFac);
if (Settings & CMaterial::eIndStage)
ui->IndTextureResSelector->SetText(QString::fromStdString(mpCurrentMat->IndTexture()->FullSource()));
else
ui->IndTextureResSelector->SetText("");
for (u32 iKonst = 0; iKonst < 4; iKonst++)
{
QColor Color;
CColor KColor = mpCurrentMat->Konst(iKonst);
Color.setRed(KColor.r);
Color.setGreen(KColor.g);
Color.setBlue(KColor.b);
Color.setAlpha(KColor.a);
if (iKonst == 0) ui->KonstColorPickerA->setColor(Color);
else if (iKonst == 1) ui->KonstColorPickerB->setColor(Color);
else if (iKonst == 2) ui->KonstColorPickerC->setColor(Color);
else if (iKonst == 3) ui->KonstColorPickerD->setColor(Color);
}
u32 PassCount = mpCurrentMat->PassCount();
ui->PassTable->clear();
ui->PassTable->setRowCount(PassCount);
for (u32 iPass = 0; iPass < PassCount; iPass++)
{
CMaterialPass *pPass = mpCurrentMat->Pass(iPass);
QTableWidgetItem *pItemA = new QTableWidgetItem("Pass #" + QString::number(iPass + 1) + ": " + QString::fromStdString(pPass->NamedType()));
QTableWidgetItem *pItemB = new QTableWidgetItem();
if (pPass->IsEnabled())
pItemB->setIcon(QIcon(":/icons/EditorAssets/Show.png"));
else
pItemB->setIcon(QIcon(":/icons/EditorAssets/Hide.png"));
ui->PassTable->setItem(iPass, 0, pItemA);
ui->PassTable->setItem(iPass, 1, pItemB);
}
// Set up the tex coord source combo box so it only shows vertex attributes that exist on this material
ui->TexCoordSrcComboBox->clear();
EVertexDescription Desc = mpCurrentMat->VtxDesc();
ui->TexCoordSrcComboBox->addItem("None");
if (Desc & ePosition) ui->TexCoordSrcComboBox->addItem("Position");
if (Desc & eNormal) ui->TexCoordSrcComboBox->addItem("Normal");
if (Desc & eTex0) ui->TexCoordSrcComboBox->addItem("Tex Coord 1");
if (Desc & eTex1) ui->TexCoordSrcComboBox->addItem("Tex Coord 2");
if (Desc & eTex2) ui->TexCoordSrcComboBox->addItem("Tex Coord 3");
if (Desc & eTex3) ui->TexCoordSrcComboBox->addItem("Tex Coord 4");
if (Desc & eTex4) ui->TexCoordSrcComboBox->addItem("Tex Coord 5");
if (Desc & eTex5) ui->TexCoordSrcComboBox->addItem("Tex Coord 6");
if (Desc & eTex6) ui->TexCoordSrcComboBox->addItem("Tex Coord 7");
if (Desc & eTex7) ui->TexCoordSrcComboBox->addItem("Tex Coord 8");
// Emit signal from Pass Table to set up the Pass UI
mIgnoreSignals = false;
if (PassCount > 0)
ui->PassTable->cellClicked(0,0);
// Activate UI
ActivateMatEditUI(true);
}
void CModelEditorWindow::SetActivePass(int PassIndex)
{
// Some modifications have to be made to the values to match GX enums with combo box indices
mIgnoreSignals = true;
mpCurrentPass = mpCurrentMat->Pass(PassIndex);
u32 KColor = mpCurrentPass->KColorSel();
u32 KAlpha = mpCurrentPass->KAlphaSel();
u32 Ras = mpCurrentPass->RasSel();
u32 TexCoordSrc = mpCurrentPass->TexCoordSource();
if (KColor >= 0xC) KColor -= 4;
if (KAlpha >= 0x10) KAlpha -= 8;
if (Ras == 0xFF) Ras = 10;
if (TexCoordSrc == 0xFF) TexCoordSrc = 0;
else TexCoordSrc++;
if (TexCoordSrc >= 5) TexCoordSrc -= 2;
CTexture *pPassTex = mpCurrentPass->Texture();
if (pPassTex)
ui->PassTextureResSelector->SetText(QString::fromStdString(pPassTex->FullSource()));
else
ui->PassTextureResSelector->SetText("");
ui->TevKColorSelComboBox->setCurrentIndex(KColor);
ui->TevKAlphaSelComboBox->setCurrentIndex(KAlpha);
ui->TevRasSelComboBox->setCurrentIndex(Ras);
ui->TexCoordSrcComboBox->setCurrentIndex(TexCoordSrc);
ui->TevColor1ComboBox->setCurrentIndex(mpCurrentPass->ColorInput(0));
ui->TevColor2ComboBox->setCurrentIndex(mpCurrentPass->ColorInput(1));
ui->TevColor3ComboBox->setCurrentIndex(mpCurrentPass->ColorInput(2));
ui->TevColor4ComboBox->setCurrentIndex(mpCurrentPass->ColorInput(3));
ui->TevColorOutputComboBox->setCurrentIndex(mpCurrentPass->ColorOutput());
ui->TevAlpha1ComboBox->setCurrentIndex(mpCurrentPass->AlphaInput(0));
ui->TevAlpha2ComboBox->setCurrentIndex(mpCurrentPass->AlphaInput(1));
ui->TevAlpha3ComboBox->setCurrentIndex(mpCurrentPass->AlphaInput(2));
ui->TevAlpha4ComboBox->setCurrentIndex(mpCurrentPass->AlphaInput(3));
ui->TevAlphaOutputComboBox->setCurrentIndex(mpCurrentPass->AlphaOutput());
s32 AnimMode = mpCurrentPass->AnimMode();
ui->AnimTypeComboBox->setCurrentIndex(AnimMode + 1);
UpdateAnimParamUI(AnimMode);
mIgnoreSignals = false;
}
void CModelEditorWindow::UpdateMaterial()
{
// This function takes input from buttons
if (!mpCurrentMat) return;
if (mIgnoreSignals) return;
EModelEditorWidget Widget = (EModelEditorWidget) sender()->property("ModelEditorWidgetType").toInt();
switch (Widget)
{
/*case eAddPassButton:
break;
case eDeletePassButton:
break;*/
}
}
void CModelEditorWindow::UpdateMaterial(int Value)
{
// This function takes input from combo boxes
if (!mpCurrentMat) return;
if (mIgnoreSignals) return;
EModelEditorWidget Widget = (EModelEditorWidget) sender()->property("ModelEditorWidgetType").toInt();
switch (Widget)
{
case eSourceBlendComboBox:
case eDestBlendComboBox:
{
GLenum SourceFac = ui->SourceBlendComboBox->currentIndex();
GLenum DstFac = ui->DestBlendComboBox->currentIndex();
if (SourceFac > 1) SourceFac += 0x2FE;
if (DstFac > 1) DstFac += 0x2FE;
mpCurrentMat->SetBlendMode(SourceFac, DstFac);
break;
}
case eTevKColorSelComboBox:
if (Value >= 8) Value += 4;
mpCurrentPass->SetKColorSel((ETevKSel) Value);
break;
case eTevKAlphaSelComboBox:
if (Value >= 8) Value += 8;
mpCurrentPass->SetKAlphaSel((ETevKSel) Value);
break;
case eTevRasSelComboBox:
if (Value == 7) Value = eRasColorNull;
mpCurrentPass->SetRasSel((ETevRasSel) Value);
break;
case eTevTexSelComboBox:
// todo
break;
case eTevTexSourceComboBox:
if (Value >= 3) Value ++;
else Value--;
mpCurrentPass->SetTexCoordSource(Value);
break;
case eTevColorComboBoxA:
case eTevColorComboBoxB:
case eTevColorComboBoxC:
case eTevColorComboBoxD:
{
ETevColorInput A = (ETevColorInput) ui->TevColor1ComboBox->currentIndex();
ETevColorInput B = (ETevColorInput) ui->TevColor2ComboBox->currentIndex();
ETevColorInput C = (ETevColorInput) ui->TevColor3ComboBox->currentIndex();
ETevColorInput D = (ETevColorInput) ui->TevColor4ComboBox->currentIndex();
mpCurrentPass->SetColorInputs(A, B, C, D);
break;
}
case eTevColorOutputComboBox:
mpCurrentPass->SetColorOutput((ETevOutput) Value);
break;
case eTevAlphaComboBoxA:
case eTevAlphaComboBoxB:
case eTevAlphaComboBoxC:
case eTevAlphaComboBoxD:
{
ETevAlphaInput A = (ETevAlphaInput) ui->TevAlpha1ComboBox->currentIndex();
ETevAlphaInput B = (ETevAlphaInput) ui->TevAlpha2ComboBox->currentIndex();
ETevAlphaInput C = (ETevAlphaInput) ui->TevAlpha3ComboBox->currentIndex();
ETevAlphaInput D = (ETevAlphaInput) ui->TevAlpha4ComboBox->currentIndex();
mpCurrentPass->SetAlphaInputs(A, B, C, D);
break;
}
case eTevAlphaOutputComboBox:
mpCurrentPass->SetAlphaOutput((ETevOutput) Value);
break;
case eAnimModeComboBox:
mpCurrentPass->SetAnimMode((EUVAnimMode) (Value - 1));
UpdateAnimParamUI(Value - 1);
break;
}
mpCurrentMat->GenerateShader();
}
void CModelEditorWindow::UpdateMaterial(int ValueA, int ValueB)
{
// This function takes input from PassTable
if (!mpCurrentMat) return;
if (mIgnoreSignals) return;
// Select Pass
if (ValueB == 0)
{
SetActivePass(ValueA);
ui->PassTable->setSelectionMode(QAbstractItemView::SingleSelection);
ui->PassTable->selectRow(ValueA);
ui->PassTable->setSelectionMode(QAbstractItemView::NoSelection);
}
// Show/Hide Pass
else if (ValueB == 1)
{
bool Enabled = !mpCurrentMat->Pass(ValueA)->IsEnabled();
mpCurrentMat->Pass(ValueA)->SetEnabled(Enabled);
if (Enabled)
ui->PassTable->item(ValueA, ValueB)->setIcon(QIcon(":/icons/EditorAssets/Show.png"));
else
ui->PassTable->item(ValueA, ValueB)->setIcon(QIcon(":/icons/EditorAssets/Hide.png"));
}
}
void CModelEditorWindow::UpdateMaterial(double Value)
{
// This function takes input from WDraggableSpinBoxes
if (!mpCurrentMat) return;
if (mIgnoreSignals) return;
EModelEditorWidget Widget = (EModelEditorWidget) sender()->property("ModelEditorWidgetType").toInt();
switch (Widget)
{
case eAnimParamASpinBox:
mpCurrentPass->SetAnimParam(0, (float) Value);
break;
case eAnimParamBSpinBox:
mpCurrentPass->SetAnimParam(1, (float) Value);
break;
case eAnimParamCSpinBox:
mpCurrentPass->SetAnimParam(2, (float) Value);
break;
case eAnimParamDSpinBox:
mpCurrentPass->SetAnimParam(3, (float) Value);
break;
}
}
void CModelEditorWindow::UpdateMaterial(bool Value)
{
// This function takes input from checkboxes
if (!mpCurrentMat) return;
if (mIgnoreSignals) return;
EModelEditorWidget Widget = (EModelEditorWidget) sender()->property("ModelEditorWidgetType").toInt();
switch (Widget)
{
case eEnableTransparencyCheckBox:
case eEnablePunchthroughCheckBox:
case eEnableReflectionCheckBox:
case eEnableSurfaceReflectionCheckBox:
case eEnableDepthWriteCheckBox:
case eEnableOccluderCheckBox:
case eEnableLightmapCheckBox:
{
CMaterial::EMaterialOptions Options = (CMaterial::EMaterialOptions) (mpCurrentMat->Options() & 0x2408);
Options |= (ui->EnableTransparencyCheck->isChecked() << 4);
Options |= (ui->EnablePunchthroughCheck->isChecked() << 5);
Options |= (ui->EnableReflectionCheck->isChecked() << 6);
Options |= (ui->EnableDepthWriteCheck->isChecked() << 7);
Options |= (ui->EnableSurfaceReflectionCheck->isChecked() << 8);
Options |= (ui->EnableOccluderCheck->isChecked() << 9);
Options |= (ui->EnableLightmapCheck->isChecked() << 11);
mpCurrentMat->SetOptions(Options);
break;
}
case eEnableLightingCheckBox:
mpCurrentMat->SetLightingEnabled(Value);
break;
}
}
void CModelEditorWindow::UpdateMaterial(QColor Color)
{
// This function takes input from WColorPickers
if (!mpCurrentMat) return;
if (mIgnoreSignals) return;
EModelEditorWidget Widget = (EModelEditorWidget) sender()->property("ModelEditorWidgetType").toInt();
CColor KColor((u8) Color.red(), (u8) Color.green(), (u8) Color.blue(), (u8) Color.alpha());
switch (Widget)
{
case eKonstColorPickerA:
mpCurrentMat->SetKonst(KColor, 0);
break;
case eKonstColorPickerB:
mpCurrentMat->SetKonst(KColor, 1);
break;
case eKonstColorPickerC:
mpCurrentMat->SetKonst(KColor, 2);
break;
case eKonstColorPickerD:
mpCurrentMat->SetKonst(KColor, 3);
break;
}
}
void CModelEditorWindow::UpdateUI(int Value)
{
EModelEditorWidget Widget = (EModelEditorWidget) sender()->property("ModelEditorWidgetType").toInt();
switch (Widget)
{
case eSetSelectComboBox:
mpCurrentModelNode->SetMatSet(Value);
SetActiveMaterial(ui->MatSelectionComboBox->currentIndex());
break;
case eMatSelectComboBox:
SetActiveMaterial(Value);
ActivateMatEditUI(true);
break;
}
}
void CModelEditorWindow::PaintViewport(CCamera& Camera)
{
mpRenderer->BeginFrame();
Camera.LoadMatrices();
if (!mpCurrentModel)
{
CDrawUtil::DrawGrid();
}
else if (mDrawMode == eDrawMesh)
{
CDrawUtil::DrawGrid();
mpCurrentModelNode->AddToRenderer(mpRenderer);
mpRenderer->RenderScene(Camera);
}
else if (mDrawMode == eDrawSphere)
{
if (!mpCurrentMat) return;
glEnable(GL_CULL_FACE);
CGraphics::sVertexBlock.COLOR0_Amb = CGraphics::skDefaultAmbientColor.ToVector4f();
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
CGraphics::UpdateMVPBlock();
CGraphics::SetDefaultLighting();
CGraphics::UpdateLightBlock(); // Note: vertex block is updated by the material
mpCurrentMat->SetCurrent(eEnableUVScroll | eEnableBackfaceCull | eEnableOccluders);
CDrawUtil::DrawSphere(true);
}
else if (mDrawMode == eDrawSquare)
{
if (!mpCurrentMat) return;
glDisable(GL_CULL_FACE);
CGraphics::SetDefaultLighting();
CGraphics::UpdateLightBlock();
CGraphics::sVertexBlock.COLOR0_Amb = CGraphics::skDefaultAmbientColor.ToVector4f();
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
CGraphics::sMVPBlock.ViewMatrix = CMatrix4f::skIdentity;
CGraphics::sMVPBlock.ProjectionMatrix = CMatrix4f::skIdentity;
CGraphics::UpdateMVPBlock();
mpCurrentMat->SetCurrent(eEnableUVScroll | eEnableOccluders);
CDrawUtil::DrawSquare();
}
mpRenderer->EndFrame();
}
void CModelEditorWindow::SetViewportSize(int Width, int Height)
{
mViewportAspectRatio = (float) Width / (float) Height;
mpRenderer->SetViewportSize(Width, Height);
}
// ************ PRIVATE ************
void CModelEditorWindow::ActivateMatEditUI(bool Active)
{
ui->MatSelectionComboBox->setEnabled(Active);
ui->GeneralGroupBox->setEnabled(Active);
ui->PassGroupBox->setEnabled(Active);
}
void CModelEditorWindow::RefreshMaterial()
{
if (mpCurrentMat) mpCurrentMat->GenerateShader();
}
void CModelEditorWindow::UpdateAnimParamUI(int Mode)
{
// Update the param labels with actual names + hide unused params for each mode.
switch (Mode)
{
case -1: // N/A
case 0: // ModelView No Translate
case 1: // ModelView
case 6: // Model
ui->AnimParamALabel->hide();
ui->AnimParamBLabel->hide();
ui->AnimParamCLabel->hide();
ui->AnimParamDLabel->hide();
ui->AnimParamASpinBox->hide();
ui->AnimParamBSpinBox->hide();
ui->AnimParamCSpinBox->hide();
ui->AnimParamDSpinBox->hide();
break;
case 2: // UV Scroll
ui->AnimParamALabel->setText("<b>Horizontal Offset:</b>");
ui->AnimParamBLabel->setText("<b>Vertical Offset:</b>");
ui->AnimParamCLabel->setText("<b>Horizontal Scale:</b>");
ui->AnimParamDLabel->setText("<b>Vertical Scale:</b>");
ui->AnimParamASpinBox->setValue(mpCurrentPass->AnimParam(0));
ui->AnimParamBSpinBox->setValue(mpCurrentPass->AnimParam(1));
ui->AnimParamCSpinBox->setValue(mpCurrentPass->AnimParam(2));
ui->AnimParamDSpinBox->setValue(mpCurrentPass->AnimParam(3));
ui->AnimParamALabel->show();
ui->AnimParamBLabel->show();
ui->AnimParamCLabel->show();
ui->AnimParamDLabel->show();
ui->AnimParamASpinBox->show();
ui->AnimParamBSpinBox->show();
ui->AnimParamCSpinBox->show();
ui->AnimParamDSpinBox->show();
break;
case 3: // Rotation
ui->AnimParamALabel->setText("<b>Offset:</b>");
ui->AnimParamBLabel->setText("<b>Scale:</b>");
ui->AnimParamASpinBox->setValue(mpCurrentPass->AnimParam(0));
ui->AnimParamBSpinBox->setValue(mpCurrentPass->AnimParam(1));
ui->AnimParamALabel->show();
ui->AnimParamBLabel->show();
ui->AnimParamCLabel->hide();
ui->AnimParamDLabel->hide();
ui->AnimParamASpinBox->show();
ui->AnimParamBSpinBox->show();
ui->AnimParamCSpinBox->hide();
ui->AnimParamDSpinBox->hide();
break;
case 4: // Horizontal Filmstrip
case 5: // Vertical Filmstrip
ui->AnimParamALabel->setText("<b>Scale:</b>");
ui->AnimParamBLabel->setText("<b>Num Frames:</b>");
ui->AnimParamCLabel->setText("<b>Step:</b>");
ui->AnimParamDLabel->setText("<b>Time Offset:</bB>");
ui->AnimParamASpinBox->setValue(mpCurrentPass->AnimParam(0));
ui->AnimParamBSpinBox->setValue(mpCurrentPass->AnimParam(1));
ui->AnimParamCSpinBox->setValue(mpCurrentPass->AnimParam(2));
ui->AnimParamDSpinBox->setValue(mpCurrentPass->AnimParam(3));
ui->AnimParamALabel->show();
ui->AnimParamBLabel->show();
ui->AnimParamCLabel->show();
ui->AnimParamDLabel->show();
ui->AnimParamASpinBox->show();
ui->AnimParamBSpinBox->show();
ui->AnimParamCSpinBox->show();
ui->AnimParamDSpinBox->show();
break;
case 7: // Mysterious mode 7
ui->AnimParamALabel->setText("<b>ParamA:</b>");
ui->AnimParamBLabel->setText("<b>ParamB:</b>");
ui->AnimParamASpinBox->setValue(mpCurrentPass->AnimParam(0));
ui->AnimParamBSpinBox->setValue(mpCurrentPass->AnimParam(1));
ui->AnimParamALabel->show();
ui->AnimParamBLabel->show();
ui->AnimParamCLabel->hide();
ui->AnimParamDLabel->hide();
ui->AnimParamASpinBox->show();
ui->AnimParamBSpinBox->show();
ui->AnimParamCSpinBox->hide();
ui->AnimParamDSpinBox->hide();
break;
}
}
void CModelEditorWindow::on_actionConvert_to_DDS_triggered()
{
QString TexFilename = QFileDialog::getOpenFileName(this, "Retro Texture (*.TXTR)", "", "*.TXTR");
if (TexFilename.isEmpty()) return;
CTexture *Tex = (CTexture*) gResCache.GetResource(TexFilename.toStdString());
std::string OutName = StringUtil::GetPathWithoutExtension(TexFilename.toStdString()) + ".dds";
CFileOutStream Out(OutName, IOUtil::LittleEndian);
if (!Out.IsValid()) QMessageBox::warning(this, "Error", "Couldn't open output DDS!");
else
{
bool success = Tex->WriteDDS(Out);
if (!success) QMessageBox::warning(this, "Error", "Couldn't write output DDS!");
else QMessageBox::information(this, "Success", "Successfully converted to DDS!");
}
}
void CModelEditorWindow::on_actionOpen_triggered()
{
QString ModelFilename = QFileDialog::getOpenFileName(this, "Retro Model (*.CMDL)", "", "*.CMDL");
if (ModelFilename.isEmpty()) return;
CModel *Model = (CModel*) gResCache.GetResource(ModelFilename.toStdString());
if (Model)
{
SetActiveModel(Model);
setWindowTitle("Prime World Editor - Model Editor: " + QString::fromStdString(Model->Source()));
}
gResCache.Clean();
}
void CModelEditorWindow::on_actionSave_triggered()
{
if (!mpCurrentModel) return;
CFileOutStream CMDLOut(mpCurrentModel->Source(), IOUtil::BigEndian);
CModelCooker::WriteCookedModel(mpCurrentModel, ePrime, CMDLOut);
QMessageBox::information(this, "Saved", "Model saved!");
}
void CModelEditorWindow::closeEvent(QCloseEvent*)
{
emit Closed();
}
void CModelEditorWindow::on_MeshPreviewButton_clicked()
{
mDrawMode = eDrawMesh;
}
void CModelEditorWindow::on_SpherePreviewButton_clicked()
{
mDrawMode = eDrawSphere;
}
void CModelEditorWindow::on_FlatPreviewButton_clicked()
{
mDrawMode = eDrawSquare;
}
void CModelEditorWindow::on_ClearColorPicker_colorChanged(const QColor &Color)
{
CColor NewColor((u8) Color.red(), (u8) Color.green(), (u8) Color.blue(), 255);
mpRenderer->SetClearColor(NewColor);
}

122
UI/CModelEditorWindow.h Normal file
View File

@@ -0,0 +1,122 @@
#ifndef CMODELEDITORWINDOW_H
#define CMODELEDITORWINDOW_H
#include <QMainWindow>
#include <Core/CRenderer.h>
#include <Core/CResCache.h>
#include <Core/CSceneManager.h>
#include <Resource/CFont.h>
#include <Resource/model/CModel.h>
#include <Scene/CModelNode.h>
namespace Ui {
class CModelEditorWindow;
}
class CModelEditorWindow : public QMainWindow
{
Q_OBJECT
enum EDrawMode {
eDrawMesh, eDrawSphere, eDrawSquare
};
Ui::CModelEditorWindow *ui;
CRenderer *mpRenderer;
CSceneManager *mpScene;
CModel *mpCurrentModel;
CToken mModelToken;
CModelNode *mpCurrentModelNode;
CMaterial *mpCurrentMat;
CMaterialPass *mpCurrentPass;
bool mIgnoreSignals;
EDrawMode mDrawMode;
float mViewportAspectRatio;
public:
explicit CModelEditorWindow(QWidget *parent = 0);
~CModelEditorWindow();
void SetActiveModel(CModel *pModel);
void closeEvent(QCloseEvent *pEvent);
public slots:
void SetActiveMaterial(int MatIndex);
void SetActivePass(int PassIndex);
void UpdateMaterial();
void UpdateMaterial(int Value);
void UpdateMaterial(int ValueA, int ValueB);
void UpdateMaterial(double Value);
void UpdateMaterial(bool Value);
void UpdateMaterial(QColor eColorProperty);
void UpdateUI(int Value);
void UpdateAnimParamUI(int Mode);
void PaintViewport(CCamera& Camera);
void SetViewportSize(int Width, int Height);
private:
void ActivateMatEditUI(bool Active);
void RefreshMaterial();
enum EModelEditorWidget
{
eSetSelectComboBox,
eMatSelectComboBox,
eEnableTransparencyCheckBox,
eEnablePunchthroughCheckBox,
eEnableReflectionCheckBox,
eEnableSurfaceReflectionCheckBox,
eEnableDepthWriteCheckBox,
eEnableOccluderCheckBox,
eEnableLightmapCheckBox,
eEnableLightingCheckBox,
eSourceBlendComboBox,
eDestBlendComboBox,
eIndTextureResSelector,
eKonstColorPickerA,
eKonstColorPickerB,
eKonstColorPickerC,
eKonstColorPickerD,
ePassTableWidget,
eTevKColorSelComboBox,
eTevKAlphaSelComboBox,
eTevRasSelComboBox,
eTevTexSelComboBox,
eTevTexSourceComboBox,
ePassTextureResSelector,
eTevColorComboBoxA,
eTevColorComboBoxB,
eTevColorComboBoxC,
eTevColorComboBoxD,
eTevColorOutputComboBox,
eTevAlphaComboBoxA,
eTevAlphaComboBoxB,
eTevAlphaComboBoxC,
eTevAlphaComboBoxD,
eTevAlphaOutputComboBox,
eAnimModeComboBox,
eAnimParamASpinBox,
eAnimParamBSpinBox,
eAnimParamCSpinBox,
eAnimParamDSpinBox,
};
private slots:
void on_actionConvert_to_DDS_triggered();
void on_actionOpen_triggered();
void on_actionSave_triggered();
void on_MeshPreviewButton_clicked();
void on_SpherePreviewButton_clicked();
void on_FlatPreviewButton_clicked();
void on_ClearColorPicker_colorChanged(const QColor &);
signals:
void Closed();
};
#endif // CMODELEDITORWINDOW_H

2502
UI/CModelEditorWindow.ui Normal file

File diff suppressed because it is too large Load Diff

58
UI/CNodeSelection.cpp Normal file
View File

@@ -0,0 +1,58 @@
#include "CNodeSelection.h"
CSceneSelection::CSceneSelection(CSceneManager *pScene)
{
mpScene = pScene;
}
void CSceneSelection::SelectNode(CSceneNode *pNode)
{
// There shouldn't be more than one selection per scene, so this should be safe.
if (!pNode->IsSelected())
{
pNode->SetSelected(true);
mSelectedNodes.push_back(pNode);
}
}
void CSceneSelection::DeselectNode(CSceneNode *pNode)
{
if (pNode->IsSelected())
{
pNode->SetSelected(false);
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
{
if (*it == pNode)
{
mSelectedNodes.erase(it);
break;
}
}
}
}
u32 CSceneSelection::SelectionSize()
{
return mSelectedNodes.size();
}
CSceneNode* CSceneSelection::NodeByIndex(u32 Index)
{
if (Index >= SelectionSize()) return nullptr;
return mSelectedNodes[Index];
}
void CSceneSelection::ClearSelection()
{
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
(*it)->SetSelected(false);
mSelectedNodes.clear();
}
// ************ OPERATORS ************
CSceneNode* CSceneSelection::operator[](u32 Index)
{
return NodeByIndex(Index);
}

24
UI/CNodeSelection.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef CNODESELECTION_H
#define CNODESELECTION_H
#include <list>
#include <Scene/CSceneNode.h>
class CSceneSelection
{
CSceneManager *mpScene;
std::vector<CSceneNode*> mSelectedNodes;
public:
CSceneSelection(CSceneManager *pScene);
void SelectNode(CSceneNode *pNode);
void DeselectNode(CSceneNode *pNode);
u32 SelectionSize();
CSceneNode* NodeByIndex(u32 Index);
void ClearSelection();
// Operators
CSceneNode* operator[](u32 Index);
};
#endif // CNODESELECTION_H

12
UI/CSimpleDelegate.cpp Normal file
View File

@@ -0,0 +1,12 @@
#include "CSimpleDelegate.h"
CSimpleDelegate::CSimpleDelegate()
{
}
CSimpleDelegate::~CSimpleDelegate()
{
}

12
UI/CSimpleDelegate.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef CSIMPLEDELEGATE_H
#define CSIMPLEDELEGATE_H
class CSimpleDelegate
{
public:
CSimpleDelegate();
~CSimpleDelegate();
};
#endif // CSIMPLEDELEGATE_H

181
UI/CStartWindow.cpp Normal file
View File

@@ -0,0 +1,181 @@
#include "CStartWindow.h"
#include "ui_CStartWindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include "CModelEditorWindow.h"
#include "CWorldEditor.h"
#include <Core/CResCache.h>
CStartWindow::CStartWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::CStartWindow)
{
ui->setupUi(this);
mpWorld = nullptr;
mpWorldEditor = new CWorldEditor(0);
mpModelEditor = new CModelEditorWindow(this);
}
CStartWindow::~CStartWindow()
{
delete ui;
delete mpWorldEditor;
delete mpModelEditor;
}
void CStartWindow::on_actionOpen_MLVL_triggered()
{
QString WorldFile = QFileDialog::getOpenFileName(this, "Open MLVL", "", "Metroid Prime World (*.MLVL)");
if (WorldFile.isEmpty()) return;
gResCache.SetFolder(StringUtil::GetFileDirectory(WorldFile.toStdString()));
mpWorld = (CWorld*) gResCache.GetResource(WorldFile.toStdString());
mWorldToken = CToken(mpWorld);
mpWorldEditor->close();
FillWorldUI();
}
void CStartWindow::FillWorldUI()
{
CStringTable *pWorldName = mpWorld->GetWorldName();
if (pWorldName)
{
std::wstring WorldName = pWorldName->GetString("ENGL", 0);
ui->WorldNameLabel->setText( QString("<font size=5><b>") + QString::fromStdWString(WorldName) + QString("</b></font>") );
ui->WorldNameSTRGLineEdit->setText( QString::fromStdString(pWorldName->Source()) );
}
else
{
ui->WorldNameLabel->clear();
ui->WorldNameSTRGLineEdit->clear();
}
CStringTable *pDarkWorldName = mpWorld->GetDarkWorldName();
if (pDarkWorldName)
ui->DarkWorldNameSTRGLineEdit->setText( QString::fromStdString(pDarkWorldName->Source()) );
else
ui->DarkWorldNameSTRGLineEdit->clear();
CModel *pDefaultSkybox = mpWorld->GetDefaultSkybox();
if (pDefaultSkybox)
ui->DefaultSkyboxCMDLLineEdit->setText( QString::fromStdString(pDefaultSkybox->Source()) );
else
ui->DefaultSkyboxCMDLLineEdit->clear();
CResource *pSaveWorld = mpWorld->GetSaveWorld();
if (pSaveWorld)
ui->WorldSAVWLineEdit->setText( QString::fromStdString(pSaveWorld->Source()) );
else
ui->WorldSAVWLineEdit->clear();
CResource *pMapWorld = mpWorld->GetMapWorld();
if (pMapWorld)
ui->WorldMAPWLineEdit->setText( QString::fromStdString(pMapWorld->Source()) );
else
ui->WorldMAPWLineEdit->clear();
u32 NumAreas = mpWorld->GetNumAreas();
ui->AreaSelectComboBox->blockSignals(true);
ui->AreaSelectComboBox->clear();
ui->AreaSelectComboBox->blockSignals(false);
ui->AreaSelectComboBox->setDisabled(false);
for (u32 iArea = 0; iArea < NumAreas; iArea++)
{
CStringTable *pAreaName = mpWorld->GetAreaName(iArea);
QString AreaName = (pAreaName != nullptr) ? QString::fromStdWString(pAreaName->GetString("ENGL", 0)) : QString("!!") + QString::fromStdString(mpWorld->GetAreaInternalName(iArea));
ui->AreaSelectComboBox->addItem(AreaName);
}
}
void CStartWindow::FillAreaUI()
{
ui->AreaNameLineEdit->setDisabled(false);
ui->AreaNameSTRGLineEdit->setDisabled(false);
ui->AreaMREALineEdit->setDisabled(false);
ui->AttachedAreasList->setDisabled(false);
ui->AreaSelectComboBox->blockSignals(true);
ui->AreaSelectComboBox->setCurrentIndex(mSelectedAreaIndex);
ui->AreaSelectComboBox->blockSignals(false);
ui->AreaNameLineEdit->setText( QString::fromStdString(mpWorld->GetAreaInternalName(mSelectedAreaIndex)));
CStringTable *pAreaName = mpWorld->GetAreaName(mSelectedAreaIndex);
if (pAreaName)
ui->AreaNameSTRGLineEdit->setText( QString::fromStdString( pAreaName->Source() ));
else
ui->AreaNameSTRGLineEdit->clear();
u64 MREA = mpWorld->GetAreaResourceID(mSelectedAreaIndex);
std::string MREAStr;
if (MREA & 0xFFFFFFFF00000000)
MREAStr = StringUtil::ResToStr(MREA);
else
MREAStr = StringUtil::ResToStr( (u32) MREA );
ui->AreaMREALineEdit->setText(QString::fromStdString(MREAStr) + QString(".MREA") );
u32 NumAttachedAreas = mpWorld->GetAreaAttachedCount(mSelectedAreaIndex);
ui->AttachedAreasList->clear();
for (u32 iArea = 0; iArea < NumAttachedAreas; iArea++)
{
u32 AttachedAreaIndex = mpWorld->GetAreaAttachedID(mSelectedAreaIndex, iArea);
CStringTable *AttachedAreaSTRG = mpWorld->GetAreaName(AttachedAreaIndex);
QString AttachedStr;
if (AttachedAreaSTRG)
AttachedStr = QString::fromStdWString(AttachedAreaSTRG->GetString("ENGL", 0) );
else
AttachedStr = QString("!!") + QString::fromStdString(mpWorld->GetAreaInternalName(AttachedAreaIndex));
ui->AttachedAreasList->addItem(AttachedStr);
}
ui->LaunchWorldEditorButton->setDisabled(false);
}
void CStartWindow::on_AreaSelectComboBox_currentIndexChanged(int index)
{
mSelectedAreaIndex = index;
FillAreaUI();
}
void CStartWindow::on_AttachedAreasList_doubleClicked(const QModelIndex &index)
{
mSelectedAreaIndex = mpWorld->GetAreaAttachedID(mSelectedAreaIndex, index.row());
FillAreaUI();
}
void CStartWindow::on_LaunchWorldEditorButton_clicked()
{
u64 AreaID = mpWorld->GetAreaResourceID(mSelectedAreaIndex);
CGameArea *pArea = (CGameArea*) gResCache.GetResource(AreaID, "MREA");
if (!pArea)
{
QMessageBox::warning(this, "Error", "Couldn't load area!");
mpWorldEditor->close();
}
else
{
mpWorld->SetAreaLayerInfo(pArea, mSelectedAreaIndex);
mpWorldEditor->SetArea(mpWorld, pArea);
mpWorldEditor->setWindowModality(Qt::WindowModal);
mpWorldEditor->showMaximized();
}
gResCache.Clean();
}
void CStartWindow::on_actionLaunch_model_viewer_triggered()
{
mpModelEditor->setWindowModality(Qt::ApplicationModal);
mpModelEditor->show();
}

46
UI/CStartWindow.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef PWESTARTWINDOW_H
#define PWESTARTWINDOW_H
#include <QMainWindow>
#include <Resource/CWorld.h>
#include <Core/CResCache.h>
#include "CModelEditorWindow.h"
#include "CWorldEditor.h"
namespace Ui {
class CStartWindow;
}
class CStartWindow : public QMainWindow
{
Q_OBJECT
Ui::CStartWindow *ui;
CWorld *mpWorld;
CToken mWorldToken;
u32 mSelectedAreaIndex;
CWorldEditor *mpWorldEditor;
CModelEditorWindow *mpModelEditor;
public:
explicit CStartWindow(QWidget *parent = 0);
~CStartWindow();
private slots:
void on_actionOpen_MLVL_triggered();
void on_AreaSelectComboBox_currentIndexChanged(int index);
void on_AttachedAreasList_doubleClicked(const QModelIndex &index);
void on_LaunchWorldEditorButton_clicked();
void on_actionLaunch_model_viewer_triggered();
private:
void FillWorldUI();
void FillAreaUI();
};
#endif // PWESTARTWINDOW_H

260
UI/CStartWindow.ui Normal file
View File

@@ -0,0 +1,260 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CStartWindow</class>
<widget class="QMainWindow" name="CStartWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>327</width>
<height>487</height>
</rect>
</property>
<property name="windowTitle">
<string>Prime World Editor</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="WorldNameLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="WorldGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>World</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="WorldNameSTRGLabel">
<property name="text">
<string>World Name STRG</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="WorldNameSTRGLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="DarkWorldNameSTRGLabel">
<property name="text">
<string>Dark World Name STRG</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="DarkWorldNameSTRGLineEdit"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="DefaultSkyboxCMDLLabel">
<property name="text">
<string>Default Skybox CMDL</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="DefaultSkyboxCMDLLineEdit"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="WorldSAVWLabel">
<property name="text">
<string>World SAVW</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="WorldSAVWLineEdit"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="WorldMAPWLabel">
<property name="text">
<string>World MAPW</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="WorldMAPWLineEdit"/>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="AreaGroupBox">
<property name="title">
<string>Area</string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QComboBox" name="AreaSelectComboBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="AreaNameLabel">
<property name="text">
<string>Area Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="AreaNameLineEdit">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="AreaNameSTRGLabel">
<property name="text">
<string>Area Name STRG</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="AreaNameSTRGLineEdit">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="AreaMREALabel">
<property name="text">
<string>Area MREA</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="AreaMREALineEdit">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="AttachedAreasLabel">
<property name="text">
<string>Attached Areas</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="AttachedAreasList">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="LaunchWorldEditorButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Launch World Editor</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>327</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionOpen_pak"/>
<addaction name="actionOpen_MLVL"/>
<addaction name="actionExtract_PAK"/>
</widget>
<widget class="QMenu" name="menuTools">
<property name="title">
<string>Tools</string>
</property>
<addaction name="actionLaunch_model_viewer"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuTools"/>
</widget>
<action name="actionOpen_pak">
<property name="text">
<string>Create new...</string>
</property>
</action>
<action name="actionOpen_MLVL">
<property name="text">
<string>Open</string>
</property>
</action>
<action name="actionExtract_PAK">
<property name="text">
<string>Extract PAK</string>
</property>
</action>
<action name="actionLaunch_model_viewer">
<property name="text">
<string>Launch model viewer</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

491
UI/CWorldEditor.cpp Normal file
View File

@@ -0,0 +1,491 @@
#include "CWorldEditor.h"
#include "ui_CWorldEditor.h"
#include "CEditorGLWidget.h"
#include <gtc/matrix_transform.hpp>
#include <Core/CDrawUtil.h>
#include <iostream>
#include <QOpenGLContext>
#include <QFontMetrics>
#include <Core/Log.h>
#include "WorldEditor/CLayerEditor.h"
#include "WorldEditor/WModifyTab.h"
#include "WorldEditor/WInstancesTab.h"
CWorldEditor::CWorldEditor(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::CWorldEditor)
{
Log::Write("Creating World Editor");
ui->setupUi(this);
mpRenderer = new CRenderer();
mpRenderer->SetClearColor(CColor::skBlack);
QSize ViewSize = ui->MainViewport->size();
mpRenderer->SetViewportSize(ViewSize.width(), ViewSize.height());
mpSceneManager = new CSceneManager();
mpArea = nullptr;
mpWorld = nullptr;
mpHoverNode = nullptr;
//mpInstanceModel = new CInstanceModel(this);
//ui->InstancesTreeView->setModel(mpInstanceModel);
mDrawSky = true;
mFrameCount = 0;
mFPSTimer.Start();
// Create blank title bar with some space to allow for dragging the dock
QWidget *pOldTitleBar = ui->MainDock->titleBarWidget();
QWidget *pNewTitleBar = new QWidget(ui->MainDock);
QVBoxLayout *pTitleLayout = new QVBoxLayout(pNewTitleBar);
pTitleLayout->setSpacing(10);
pNewTitleBar->setLayout(pTitleLayout);
ui->MainDock->setTitleBarWidget(pNewTitleBar);
delete pOldTitleBar;
ResetHover();
ui->ModifyTabContents->SetEditor(this);
ui->InstancesTabContents->SetEditor(this, mpSceneManager);
ui->MainDock->installEventFilter(this);
connect(ui->MainViewport, SIGNAL(PreRender()), this, SLOT(ViewportPreRender()));
connect(ui->MainViewport, SIGNAL(Render(CCamera&)), this, SLOT(ViewportRender(CCamera&)));
connect(ui->MainViewport, SIGNAL(ViewportResized(int,int)), this, SLOT(SetViewportSize(int,int)));
connect(ui->MainViewport, SIGNAL(frameSwapped()), this, SLOT(ViewportPostRender()));
connect(ui->MainViewport, SIGNAL(MouseClick(QMouseEvent*)), this, SLOT(ViewportMouseClick(QMouseEvent*)));
}
CWorldEditor::~CWorldEditor()
{
delete ui;
}
bool CWorldEditor::eventFilter(QObject *pObj, QEvent *pEvent)
{
if (pObj == ui->MainDock)
{
if (pEvent->type() == QEvent::Resize)
{
UpdateSelectionUI();
}
}
return false;
}
void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
{
ResetHover();
ClearSelection();
ui->ModifyTabContents->ClearUI();
ui->ModifyTabContents->ClearCachedEditors();
ui->InstancesTabContents->SetMaster(nullptr);
ui->InstancesTabContents->SetArea(pArea);
// Clear old area - hack until better world/area loader is implemented
if ((mpArea) && (pArea != mpArea))
mpArea->ClearScriptLayers();
// Load new area
mpArea = pArea;
mpWorld = pWorld;
mAreaToken = CToken(pArea);
mWorldToken = CToken(pWorld);
mpSceneManager->SetActiveWorld(pWorld);
mpSceneManager->SetActiveArea(pArea);
// Snap camera to location of area
CTransform4f AreaTransform = pArea->GetTransform();
CVector3f AreaPosition(AreaTransform[0][3], AreaTransform[1][3], AreaTransform[2][3]);
ui->MainViewport->Camera().Snap(AreaPosition);
// Default bloom to ON for Metroid Prime 3; disable for other games
if (mpWorld->Version() == eCorruption)
{
ui->menuBloom->setEnabled(true);
on_ActionBloom_triggered();
}
else
{
ui->menuBloom->setEnabled(false);
on_ActionNoBloom_triggered();
}
// Set up sidebar tabs
CMasterTemplate *pMaster = CMasterTemplate::GetMasterForGame(mpWorld->Version());
ui->InstancesTabContents->SetMaster(pMaster);
}
void CWorldEditor::ViewportRayCast(CRay Ray)
{
if (!ui->MainViewport->IsMouseInputActive())
{
SRayIntersection Result = mpSceneManager->SceneRayCast(Ray);
if (Result.Hit)
{
if (mpHoverNode)
mpHoverNode->SetMouseHovering(false);
mpHoverNode = Result.pNode;
mpHoverNode->SetMouseHovering(true);
mHoverPoint = Ray.PointOnRay(Result.Distance);
}
else
ResetHover();
}
else
ResetHover();
}
CRenderer* CWorldEditor::Renderer()
{
return mpRenderer;
}
CSceneManager* CWorldEditor::Scene()
{
return mpSceneManager;
}
CGameArea* CWorldEditor::ActiveArea()
{
return mpArea;
}
// ************ SELECTION ************
void CWorldEditor::SelectNode(CSceneNode *pNode)
{
if (!pNode->IsSelected())
{
pNode->SetSelected(true);
mSelectedNodes.push_back(pNode);
mSelectionAABox.ExpandBounds(pNode->AABox());
if (pNode->NodeType() == eScriptNode)
{
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
if (pScript->HasPreviewVolume())
mSelectionAABox.ExpandBounds(pScript->PreviewVolumeAABox());
}
}
UpdateSelectionUI();
}
void CWorldEditor::DeselectNode(CSceneNode *pNode)
{
if (pNode->IsSelected())
{
pNode->SetSelected(false);
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
{
if (*it == pNode)
{
mSelectedNodes.erase(it);
break;
}
}
}
RecalculateSelectionBounds();
UpdateSelectionUI();
}
void CWorldEditor::ClearSelection()
{
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
(*it)->SetSelected(false);
mSelectedNodes.clear();
mSelectionAABox = CAABox::skInfinite;
UpdateSelectionUI();
}
// ************ SLOTS ************
void CWorldEditor::ViewportMouseDrag(QMouseEvent *pEvent)
{
// todo: gizmo translate/rotate/scale implementation
}
void CWorldEditor::ViewportMouseClick(QMouseEvent *pEvent)
{
// Process left click (button press)
if (pEvent->button() == Qt::LeftButton)
{
bool ValidNode = ((mpHoverNode) && (mpHoverNode->NodeType() != eStaticNode));
bool AltPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
bool CtrlPressed = ((pEvent->modifiers() & Qt::ControlModifier) != 0);
// Alt pressed - deselect object
if (AltPressed)
{
// No valid node selected - do nothing
if (!ValidNode)
return;
DeselectNode(mpHoverNode);
}
// Other - select object
else
{
// Control not pressed - clear existing selection
if (!CtrlPressed)
ClearSelection();
// Add hover node to selection
if (ValidNode)
SelectNode(mpHoverNode);
}
UpdateSelectionUI();
}
// Later, possibly expand to context menu creation for right-click
}
// ************ SLOTS ************
void CWorldEditor::ViewportPreRender()
{
// Perform raycast
if (ui->MainViewport->underMouse())
ViewportRayCast(ui->MainViewport->CastRay());
else
ResetHover();
// Start frame
mFrameTimer.Start();
mpRenderer->BeginFrame();
}
void CWorldEditor::ViewportRender(CCamera& Camera)
{
mpSceneManager->AddSceneToRenderer(mpRenderer);
if (mDrawSky)
{
CModel *pSky = mpSceneManager->GetActiveSkybox();
if (pSky) mpRenderer->RenderSky(pSky, Camera.Position());
}
mpRenderer->RenderScene(Camera);
mpRenderer->EndFrame();
mFrameTimer.Stop();
mFrameCount++;
}
void CWorldEditor::ViewportPostRender()
{
// Update UI with raycast results
UpdateCursor();
UpdateStatusBar();
}
void CWorldEditor::SetViewportSize(int Width, int Height)
{
mpRenderer->SetViewportSize(Width, Height);
}
// ************ PRIVATE ************
void CWorldEditor::RecalculateSelectionBounds()
{
mSelectionAABox = CAABox::skInfinite;
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
{
mSelectionAABox.ExpandBounds( (*it)->AABox() );
if ((*it)->NodeType() == eScriptNode)
{
CScriptNode *pScript = static_cast<CScriptNode*>(*it);
if (pScript->HasPreviewVolume())
mSelectionAABox.ExpandBounds(pScript->PreviewVolumeAABox());
}
}
}
void CWorldEditor::ResetHover()
{
if (mpHoverNode) mpHoverNode->SetMouseHovering(false);
mpHoverNode = nullptr;
mHoverPoint = CVector3f::skZero;
}
void CWorldEditor::UpdateCursor()
{
if (ui->MainViewport->IsCursorVisible())
{
if ((mpHoverNode) && (mpHoverNode->NodeType() != eStaticNode))
ui->MainViewport->SetCursorState(Qt::PointingHandCursor);
else
ui->MainViewport->SetCursorState(Qt::ArrowCursor);
}
}
void CWorldEditor::UpdateStatusBar()
{
// Would be cool to do more frequent status bar updates with more info. Unfortunately, this causes lag.
QString StatusText = "";
if (mpHoverNode)
{
if (mpHoverNode->NodeType() != eStaticNode)
StatusText = QString::fromStdString(mpHoverNode->Name());
}
if (ui->statusbar->currentMessage() != StatusText)
ui->statusbar->showMessage(StatusText);
}
void CWorldEditor::UpdateSelectionUI()
{
// Update sidebar
ui->ModifyTabContents->GenerateUI(mSelectedNodes);
// Update selection info text
QString SelectionText;
if (mSelectedNodes.size() == 1)
SelectionText = QString::fromStdString(mSelectedNodes.front()->Name());
else if (mSelectedNodes.size() > 1)
SelectionText = QString("%1 objects selected").arg(mSelectedNodes.size());
QFontMetrics Metrics(ui->SelectionInfoLabel->font());
SelectionText = Metrics.elidedText(SelectionText, Qt::ElideRight, ui->SelectionInfoFrame->width() - 10);
ui->SelectionInfoLabel->setText(SelectionText);
}
// ************ ACTIONS ************
// These functions are from "Go to slot" in the designer
void CWorldEditor::on_ActionDrawWorld_triggered()
{
mpSceneManager->SetWorld(ui->ActionDrawWorld->isChecked());
}
void CWorldEditor::on_ActionDrawCollision_triggered()
{
mpSceneManager->SetCollision(ui->ActionDrawCollision->isChecked());
}
void CWorldEditor::on_ActionDrawObjects_triggered()
{
mpSceneManager->SetObjects(ui->ActionDrawObjects->isChecked());
}
void CWorldEditor::on_ActionDrawLights_triggered()
{
mpSceneManager->SetLights(ui->ActionDrawLights->isChecked());
}
void CWorldEditor::on_ActionDrawSky_triggered()
{
mDrawSky = ui->ActionDrawSky->isChecked();
}
void CWorldEditor::on_ActionNoLighting_triggered()
{
CGraphics::sLightMode = CGraphics::NoLighting;
ui->ActionNoLighting->setChecked(true);
ui->ActionBasicLighting->setChecked(false);
ui->ActionWorldLighting->setChecked(false);
}
void CWorldEditor::on_ActionBasicLighting_triggered()
{
CGraphics::sLightMode = CGraphics::BasicLighting;
ui->ActionNoLighting->setChecked(false);
ui->ActionBasicLighting->setChecked(true);
ui->ActionWorldLighting->setChecked(false);
}
void CWorldEditor::on_ActionWorldLighting_triggered()
{
CGraphics::sLightMode = CGraphics::WorldLighting;
ui->ActionNoLighting->setChecked(false);
ui->ActionBasicLighting->setChecked(false);
ui->ActionWorldLighting->setChecked(true);
}
void CWorldEditor::on_ActionNoBloom_triggered()
{
mpRenderer->SetBloom(CRenderer::eNoBloom);
ui->ActionNoBloom->setChecked(true);
ui->ActionBloomMaps->setChecked(false);
ui->ActionBloom->setChecked(false);
}
void CWorldEditor::on_ActionBloomMaps_triggered()
{
mpRenderer->SetBloom(CRenderer::eBloomMaps);
ui->ActionNoBloom->setChecked(false);
ui->ActionBloomMaps->setChecked(true);
ui->ActionBloom->setChecked(false);
}
void CWorldEditor::on_ActionBloom_triggered()
{
mpRenderer->SetBloom(CRenderer::eBloom);
ui->ActionNoBloom->setChecked(false);
ui->ActionBloomMaps->setChecked(false);
ui->ActionBloom->setChecked(true);
}
void CWorldEditor::on_ActionZoomOnSelection_triggered()
{
static const float skDistScale = 2.5f;
static const float skAreaDistScale = 0.8f;
CCamera& Camera = ui->MainViewport->Camera();
CVector3f CamDir = Camera.GetDirection();
CVector3f NewPos;
// Zoom on selection
if (mSelectedNodes.size() != 0)
{
CVector3f Min = mSelectionAABox.Min();
CVector3f Max = mSelectionAABox.Max();
float Dist = ((Max.x - Min.x) + (Max.y - Min.y) + (Max.z - Min.z)) / 3.f;
//float Dist = mSelectionAABox.Min().Distance(mSelectionAABox.Max());
NewPos = mSelectionAABox.Center() + (CamDir * -(Dist * skDistScale));
}
// Zoom on area
else
{
CAABox AreaBox = mpArea->AABox();
CVector3f Min = AreaBox.Min();
CVector3f Max = AreaBox.Max();
float Dist = ((Max.x - Min.x) + (Max.y - Min.y) + (Max.z - Min.z)) / 3.f;
//float Dist = AreaBox.Min().Distance(AreaBox.Max());
NewPos = AreaBox.Center() + (CamDir * -(Dist * skAreaDistScale));
}
Camera.SetPosition(NewPos);
}
void CWorldEditor::on_ActionDisableBackfaceCull_triggered()
{
mpRenderer->ToggleBackfaceCull(!ui->ActionDisableBackfaceCull->isChecked());
}
void CWorldEditor::on_ActionDisableAlpha_triggered()
{
mpRenderer->ToggleAlphaDisabled(ui->ActionDisableAlpha->isChecked());
}
void CWorldEditor::on_ActionEditLayers_triggered()
{
// Launch layer editor
CLayerEditor Editor(this);
Editor.SetArea(mpArea);
Editor.exec();
}

94
UI/CWorldEditor.h Normal file
View File

@@ -0,0 +1,94 @@
#ifndef CWORLDEDITOR_H
#define CWORLDEDITOR_H
#include <QMainWindow>
#include <QList>
#include <Common/CRay.h>
#include <Common/CTimer.h>
#include <Common/EKeyInputs.h>
#include <Common/SRayIntersection.h>
#include <Core/CRenderer.h>
#include <Core/CSceneManager.h>
#include <Core/CToken.h>
#include <Resource/CGameArea.h>
#include <Resource/CWorld.h>
namespace Ui {
class CWorldEditor;
}
class CWorldEditor : public QMainWindow
{
Q_OBJECT
CRenderer *mpRenderer;
CSceneManager *mpSceneManager;
CCamera mCamera;
CGameArea *mpArea;
CWorld *mpWorld;
CToken mAreaToken;
CToken mWorldToken;
CTimer mFrameTimer;
bool mDrawSky;
CVector3f mHoverPoint;
CSceneNode *mpHoverNode;
std::list<CSceneNode*> mSelectedNodes;
CAABox mSelectionAABox;
CTimer mFPSTimer;
int mFrameCount;
public:
explicit CWorldEditor(QWidget *parent = 0);
~CWorldEditor();
bool eventFilter(QObject *pObj, QEvent *pEvent);
void SetArea(CWorld *pWorld, CGameArea *pArea);
void ViewportRayCast(CRay Ray);
CRenderer* Renderer();
CSceneManager* Scene();
CGameArea* ActiveArea();
// Selection
void SelectNode(CSceneNode *pNode);
void DeselectNode(CSceneNode *pNode);
void ClearSelection();
public slots:
void ViewportPreRender();
void ViewportRender(CCamera& Camera);
void ViewportPostRender();
void ViewportMouseDrag(QMouseEvent *pEvent);
void ViewportMouseClick(QMouseEvent *pEvent);
void SetViewportSize(int Width, int Height);
private:
Ui::CWorldEditor *ui;
void RecalculateSelectionBounds();
void ResetHover();
void UpdateCursor();
// UI
void OnSidebarResize();
void UpdateSelectionUI();
void UpdateStatusBar();
private slots:
void on_ActionDrawWorld_triggered();
void on_ActionDrawCollision_triggered();
void on_ActionDrawObjects_triggered();
void on_ActionDrawLights_triggered();
void on_ActionDrawSky_triggered();
void on_ActionNoLighting_triggered();
void on_ActionBasicLighting_triggered();
void on_ActionWorldLighting_triggered();
void on_ActionNoBloom_triggered();
void on_ActionBloomMaps_triggered();
void on_ActionBloom_triggered();
void on_ActionZoomOnSelection_triggered();
void on_ActionDisableBackfaceCull_triggered();
void on_ActionDisableAlpha_triggered();
void on_ActionEditLayers_triggered();
};
#endif // CWORLDEDITOR_H

608
UI/CWorldEditor.ui Normal file
View File

@@ -0,0 +1,608 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CWorldEditor</class>
<widget class="QMainWindow" name="CWorldEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1280</width>
<height>720</height>
</rect>
</property>
<property name="windowTitle">
<string>Prime World Editor</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="CEditorGLWidget" name="MainViewport" native="true"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1280</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="ActionOpen"/>
<addaction name="ActionSave"/>
</widget>
<widget class="QMenu" name="menuWindow">
<property name="title">
<string>Window</string>
</property>
</widget>
<widget class="QMenu" name="menuModels">
<property name="title">
<string>Models</string>
</property>
<addaction name="actionOpen_model_viewer"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>Edit</string>
</property>
<addaction name="ActionUndo"/>
<addaction name="ActionRedo"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
<widget class="QMenu" name="menuLighting">
<property name="title">
<string>Lighting</string>
</property>
<addaction name="ActionNoLighting"/>
<addaction name="ActionBasicLighting"/>
<addaction name="ActionWorldLighting"/>
</widget>
<widget class="QMenu" name="menuBloom">
<property name="title">
<string>Bloom</string>
</property>
<addaction name="ActionNoBloom"/>
<addaction name="ActionBloomMaps"/>
<addaction name="ActionBloom"/>
</widget>
<addaction name="ActionZoomOnSelection"/>
<addaction name="separator"/>
<addaction name="ActionDrawWorld"/>
<addaction name="ActionDrawCollision"/>
<addaction name="ActionDrawObjects"/>
<addaction name="ActionDrawLights"/>
<addaction name="ActionDrawSky"/>
<addaction name="separator"/>
<addaction name="menuLighting"/>
<addaction name="menuBloom"/>
<addaction name="separator"/>
<addaction name="ActionDisableBackfaceCull"/>
<addaction name="ActionDisableAlpha"/>
</widget>
<widget class="QMenu" name="menuTools">
<property name="title">
<string>Tools</string>
</property>
<addaction name="ActionEditLayers"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuTools"/>
<addaction name="menuView"/>
<addaction name="menuModels"/>
<addaction name="menuWindow"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="Toolbar">
<property name="windowTitle">
<string>toolBar_2</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="ActionOpen"/>
<addaction name="ActionSave"/>
</widget>
<widget class="QDockWidget" name="MainDock">
<property name="features">
<set>QDockWidget::DockWidgetMovable</set>
</property>
<property name="allowedAreas">
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
</property>
<property name="windowTitle">
<string/>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="MainDockContents">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QFrame" name="SelectionInfoFrame">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="SelectionInfoLabel">
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTabWidget" name="TabWidget">
<property name="tabPosition">
<enum>QTabWidget::North</enum>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="documentMode">
<bool>false</bool>
</property>
<widget class="QWidget" name="CreateTab">
<attribute name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/EditorAssets/Create.png</normaloff>:/icons/EditorAssets/Create.png</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>Create</string>
</attribute>
</widget>
<widget class="QWidget" name="ModifyTab">
<attribute name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/EditorAssets/Modify.png</normaloff>:/icons/EditorAssets/Modify.png</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>Modify</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="WModifyTab" name="ModifyTabContents" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="InstancesTab">
<attribute name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/EditorAssets/Instances.png</normaloff>:/icons/EditorAssets/Instances.png</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>Instances</string>
</attribute>
<layout class="QHBoxLayout" name="InstancesTabLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="WInstancesTab" name="InstancesTabContents" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="DisplayTab">
<attribute name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/EditorAssets/Display.png</normaloff>:/icons/EditorAssets/Display.png</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>Display</string>
</attribute>
</widget>
<widget class="QWidget" name="WorldTab">
<attribute name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/EditorAssets/World.png</normaloff>:/icons/EditorAssets/World.png</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>World</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>true</bool>
</attribute>
<addaction name="ActionLink"/>
<addaction name="ActionUnlink"/>
<addaction name="separator"/>
<addaction name="ActionTranslate"/>
<addaction name="ActionRotate"/>
<addaction name="ActionScale"/>
</widget>
<action name="ActionOpen">
<property name="text">
<string>Open</string>
</property>
</action>
<action name="ActionSave">
<property name="text">
<string>Save</string>
</property>
</action>
<action name="ActionTranslate">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/EditorAssets/Translate.png</normaloff>:/icons/EditorAssets/Translate.png</iconset>
</property>
<property name="text">
<string>Translate</string>
</property>
<property name="toolTip">
<string>Translate</string>
</property>
</action>
<action name="ActionRotate">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/EditorAssets/Rotate.png</normaloff>:/icons/EditorAssets/Rotate.png</iconset>
</property>
<property name="text">
<string>Rotate</string>
</property>
<property name="toolTip">
<string>Rotate</string>
</property>
</action>
<action name="ActionScale">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/EditorAssets/Scale.png</normaloff>:/icons/EditorAssets/Scale.png</iconset>
</property>
<property name="text">
<string>Scale</string>
</property>
<property name="toolTip">
<string>Scale</string>
</property>
</action>
<action name="actionOpen_model_viewer">
<property name="text">
<string>Open Model Viewer</string>
</property>
</action>
<action name="ActionLink">
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/EditorAssets/Link.png</normaloff>:/icons/EditorAssets/Link.png</iconset>
</property>
<property name="text">
<string>Link</string>
</property>
<property name="toolTip">
<string>Link</string>
</property>
</action>
<action name="ActionUnlink">
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/EditorAssets/Unlink.png</normaloff>:/icons/EditorAssets/Unlink.png</iconset>
</property>
<property name="text">
<string>Unlink</string>
</property>
<property name="toolTip">
<string>Unlink</string>
</property>
</action>
<action name="ActionUndo">
<property name="text">
<string>Undo</string>
</property>
<property name="shortcut">
<string>Ctrl+Z</string>
</property>
</action>
<action name="ActionRedo">
<property name="text">
<string>Redo</string>
</property>
<property name="shortcut">
<string>Ctrl+Y</string>
</property>
</action>
<action name="ActionDrawWorld">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>World</string>
</property>
<property name="shortcut">
<string>1</string>
</property>
</action>
<action name="ActionDrawCollision">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Collision</string>
</property>
<property name="shortcut">
<string>2</string>
</property>
</action>
<action name="ActionDrawObjects">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Objects</string>
</property>
<property name="shortcut">
<string>3</string>
</property>
</action>
<action name="ActionDrawLights">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Lights</string>
</property>
<property name="shortcut">
<string>4</string>
</property>
</action>
<action name="ActionDrawSky">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Sky</string>
</property>
<property name="shortcut">
<string>5</string>
</property>
</action>
<action name="ActionNoLighting">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>None</string>
</property>
<property name="shortcut">
<string>Ctrl+1</string>
</property>
</action>
<action name="ActionBasicLighting">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Basic</string>
</property>
<property name="toolTip">
<string>Basic</string>
</property>
<property name="shortcut">
<string>Ctrl+2</string>
</property>
</action>
<action name="ActionWorldLighting">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>World</string>
</property>
<property name="shortcut">
<string>Ctrl+3</string>
</property>
</action>
<action name="ActionNoBloom">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>None</string>
</property>
</action>
<action name="ActionBloomMaps">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Bloom Maps</string>
</property>
</action>
<action name="ActionBloom">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Bloom</string>
</property>
</action>
<action name="ActionZoomOnSelection">
<property name="text">
<string>Zoom On Selection</string>
</property>
<property name="shortcut">
<string>Z</string>
</property>
</action>
<action name="ActionDisableBackfaceCull">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Disable Backface Culling</string>
</property>
</action>
<action name="ActionDisableAlpha">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Disable Alpha</string>
</property>
</action>
<action name="ActionEditLayers">
<property name="text">
<string>Edit Layers</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>CEditorGLWidget</class>
<extends>QWidget</extends>
<header>CEditorGLWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>WModifyTab</class>
<extends>QWidget</extends>
<header>WorldEditor/WModifyTab.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>WInstancesTab</class>
<extends>QWidget</extends>
<header>WorldEditor/WInstancesTab.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../Icons.qrc"/>
</resources>
<connections/>
</ui>

300
UI/CWorldEditorWindow.cpp Normal file
View File

@@ -0,0 +1,300 @@
#include <iostream>
#include <QFileDialog>
#include <QMessageBox>
#include "CWorldEditorWindow.h"
#include <Resource/CTexture.h>
#include <Core/CResCache.h>
#include <Core/CSceneManager.h>
#include <FileIO/FileIO.h>
#include <Common/StringUtil.h>
#include <Core/CGraphics.h>
#include <gtc/matrix_transform.hpp>
#include "CEditorGLWidget.h"
CWorldEditorWindow::CWorldEditorWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::CWorldEditorWindow)
{
ui->setupUi(this);
mpRenderer = new CRenderer();
mpRenderer->ToggleGrid(false);
mpActiveWorld = nullptr;
mpActiveArea = nullptr;
mRendererInitialized = false;
mpSceneManager = new CSceneManager();
mCamera.Snap(CVector3f(0, 3, 1));
mCameraMode = eFreeCamera;
mViewportKeysPressed = 0;
mShouldDrawSky = true;
connect(ui->CentralGLWidget, SIGNAL(ViewportResized(int,int)), this, SLOT(SetViewportSize(int,int)));
connect(ui->CentralGLWidget, SIGNAL(PaintViewport(double)), this, SLOT(PaintViewport(double)));
connect(ui->CentralGLWidget, SIGNAL(MouseClicked(QMouseEvent*)), this, SLOT(OnViewportRayCast(QMouseEvent*)));
connect(ui->CentralGLWidget, SIGNAL(MouseMoved(QMouseEvent*, float, float)), this, SLOT(OnViewportMouseMove(QMouseEvent*, float, float)));
connect(ui->CentralGLWidget, SIGNAL(KeyPressed(QKeyEvent*)), this, SLOT(OnViewportKeyPress(QKeyEvent*)));
connect(ui->CentralGLWidget, SIGNAL(KeyReleased(QKeyEvent*)), this, SLOT(OnViewportKeyRelease(QKeyEvent*)));
connect(ui->CentralGLWidget, SIGNAL(WheelScroll(int)), this, SLOT(OnViewportWheelScroll(int)));
}
CWorldEditorWindow::~CWorldEditorWindow()
{
delete ui;
delete mpRenderer;
delete mpSceneManager;
}
void CWorldEditorWindow::InitializeWorld(CWorld *pWorld, CGameArea *pArea)
{
mpSceneManager->SetActiveWorld(pWorld);
mpSceneManager->SetActiveArea(pArea);
mpRenderer->SetClearColor(CColor::skWhite);
// Snap camera to location of area
CTransform4f AreaTransform = pArea->GetTransform();
CVector3f AreaPosition(AreaTransform[0][3], AreaTransform[1][3], AreaTransform[2][3]);
mCamera.Snap(AreaPosition);
// Set bloom based on world version
if (pWorld != mpActiveWorld)
{
if (pWorld->Version() != eCorruption)
{
ui->menuBloom->setEnabled(false);
on_actionDisableBloom_triggered();
}
else
{
ui->menuBloom->setEnabled(true);
on_actionEnableBloom_triggered();
}
}
mpActiveWorld = pWorld;
mpActiveArea = pArea;
}
// ************ PUBLIC SLOTS ************
void CWorldEditorWindow::PaintViewport(double DeltaTime)
{
if (!mRendererInitialized)
{
mpRenderer->Init();
mRendererInitialized = true;
}
mCamera.ProcessKeyInput((EKeyInputs) mViewportKeysPressed, DeltaTime);
mCamera.LoadMatrices();
mpRenderer->BeginFrame();
mpSceneManager->AddSceneToRenderer(mpRenderer);
if (mShouldDrawSky)
{
CModel *pSky = mpSceneManager->GetActiveSkybox();
if (pSky) mpRenderer->RenderSky(pSky, mCamera.Position());
}
mpRenderer->RenderScene(mCamera);
mpRenderer->EndFrame();
}
void CWorldEditorWindow::SetViewportSize(int Width, int Height)
{
mViewportAspectRatio = (float) Width / (float) Height;
mpRenderer->SetViewportSize(Width, Height);
}
void CWorldEditorWindow::OnViewportMouseMove(QMouseEvent *pEvent, float XMovement, float YMovement)
{
int KeyInputs = 0;
if (pEvent->modifiers() & Qt::ControlModifier) KeyInputs |= eCtrlKey;
if (pEvent->modifiers() & Qt::AltModifier) KeyInputs |= eAltKey;
int MouseInputs = 0;
if (pEvent->buttons() & Qt::LeftButton) MouseInputs |= eLeftButton;
if (pEvent->buttons() & Qt::MiddleButton) MouseInputs |= eMiddleButton;
if (pEvent->buttons() & Qt::RightButton) MouseInputs |= eRightButton;
mCamera.ProcessMouseInput((EKeyInputs) KeyInputs, (EMouseInputs) MouseInputs, XMovement, YMovement);
}
void CWorldEditorWindow::OnViewportKeyPress(QKeyEvent *pEvent)
{
switch (pEvent->key())
{
case Qt::Key_Q: mViewportKeysPressed |= eQKey; break;
case Qt::Key_W: mViewportKeysPressed |= eWKey; break;
case Qt::Key_E: mViewportKeysPressed |= eEKey; break;
case Qt::Key_A: mViewportKeysPressed |= eAKey; break;
case Qt::Key_S: mViewportKeysPressed |= eSKey; break;
case Qt::Key_D: mViewportKeysPressed |= eDKey; break;
}
}
void CWorldEditorWindow::OnViewportKeyRelease(QKeyEvent *pEvent)
{
switch (pEvent->key())
{
case Qt::Key_Q: mViewportKeysPressed &= ~eQKey; break;
case Qt::Key_W: mViewportKeysPressed &= ~eWKey; break;
case Qt::Key_E: mViewportKeysPressed &= ~eEKey; break;
case Qt::Key_A: mViewportKeysPressed &= ~eAKey; break;
case Qt::Key_S: mViewportKeysPressed &= ~eSKey; break;
case Qt::Key_D: mViewportKeysPressed &= ~eDKey; break;
}
}
void CWorldEditorWindow::OnViewportWheelScroll(int ScrollAmount)
{
mCamera.Zoom(ScrollAmount / 6000.f);
}
void CWorldEditorWindow::OnViewportRayCast(QMouseEvent *pEvent)
{
// todo: ray cast
}
// ************ PRIVATE SLOTS ************
void CWorldEditorWindow::LoadScriptableLayerUI()
{
}
void CWorldEditorWindow::on_actionExit_triggered()
{
close();
}
void CWorldEditorWindow::on_actionBackface_culling_triggered()
{
mpRenderer->ToggleBackfaceCull(ui->actionBackface_culling->isChecked());
}
void CWorldEditorWindow::on_actionWorld_triggered()
{
mpSceneManager->SetWorld(ui->actionWorld->isChecked());
}
void CWorldEditorWindow::on_actionCollision_triggered()
{
mpSceneManager->SetCollision(ui->actionCollision->isChecked());
}
void CWorldEditorWindow::on_actionObjects_triggered()
{
mpSceneManager->SetObjects(ui->actionObjects->isChecked());
}
void CWorldEditorWindow::setupInstanceViewLayers()
{
/* if (qApp->scene.MREAArray.empty()) return;
mrea_GL *m = qApp->scene.MREAArray[0];
if (!m->isSCLYRead()) return;
u32 layer_count = m->getLayerCount();
for (u32 l = 0; l < layer_count; l++) {
QTreeWidgetItem* layer = new QTreeWidgetItem;
layer->setText(0, "Layer " + QString::number(l));
ui->InstanceViewTreeWidget->addTopLevelItem(layer);
u32 object_count = m->getObjectCount(l);
for (u32 o = 0; o < object_count; o++) {
PrimeObject object = m->getObject(l, o);
std::string name = object.getStringProperty("Name");
if (name.empty()) name = "[no name]";
QTreeWidgetItem* obj = new QTreeWidgetItem;
obj->setText(0, QString::fromStdString(name));
obj->setText(1, QString::fromStdString(qApp->scene.getObjectName(object.type)));
obj->setToolTip(0, obj->text(0));
obj->setToolTip(1, obj->text(1));
layer->addChild(obj);
//layer->set
}
}*/
}
void CWorldEditorWindow::clearInstanceView()
{
//ui->InstanceViewTreeWidget->clear();
}
void CWorldEditorWindow::on_actionMaterial_Animations_triggered()
{
mpRenderer->ToggleUVAnimation(ui->actionMaterial_Animations->isChecked());
}
void CWorldEditorWindow::on_actionLights_triggered()
{
mpSceneManager->SetLights(ui->actionLights->isChecked());
}
void CWorldEditorWindow::on_actionLightingNone_triggered()
{
CGraphics::sLightMode = CGraphics::NoLighting;
ui->actionLightingNone->setChecked(true);
ui->actionLightingBasic->setChecked(false);
ui->actionLightingWorld->setChecked(false);
}
void CWorldEditorWindow::on_actionLightingBasic_triggered()
{
CGraphics::sLightMode = CGraphics::BasicLighting;
ui->actionLightingNone->setChecked(false);
ui->actionLightingBasic->setChecked(true);
ui->actionLightingWorld->setChecked(false);
}
void CWorldEditorWindow::on_actionLightingWorld_triggered()
{
CGraphics::sLightMode = CGraphics::WorldLighting;
ui->actionLightingNone->setChecked(false);
ui->actionLightingBasic->setChecked(false);
ui->actionLightingWorld->setChecked(true);
}
void CWorldEditorWindow::on_actionSky_triggered()
{
mShouldDrawSky = ui->actionSky->isChecked();
}
void CWorldEditorWindow::on_actionOccluder_meshes_triggered()
{
mpRenderer->ToggleOccluders(ui->actionOccluder_meshes->isChecked());
}
void CWorldEditorWindow::closeEvent(QCloseEvent *)
{
emit Closed();
}
void CWorldEditorWindow::on_actionDisableBloom_triggered()
{
mpRenderer->SetBloom(CRenderer::eNoBloom);
ui->actionEnableBloom->setChecked(false);
ui->actionDisableBloom->setChecked(true);
ui->actionShowBloomMaps->setChecked(false);
}
void CWorldEditorWindow::on_actionEnableBloom_triggered()
{
mpRenderer->SetBloom(CRenderer::eBloom);
ui->actionDisableBloom->setChecked(false);
ui->actionEnableBloom->setChecked(true);
ui->actionShowBloomMaps->setChecked(false);
}
void CWorldEditorWindow::on_actionShowBloomMaps_triggered()
{
mpRenderer->SetBloom(CRenderer::eBloomMaps);
ui->actionDisableBloom->setChecked(false);
ui->actionEnableBloom->setChecked(false);
ui->actionShowBloomMaps->setChecked(true);
}

89
UI/CWorldEditorWindow.h Normal file
View File

@@ -0,0 +1,89 @@
#ifndef CWORLDEDITORWINDOW_H
#define CWORLDEDITORWINDOW_H
#include <QMainWindow>
#include "ui_CWorldEditorWindow.h"
#include <Core/CRenderer.h>
#include <Core/CSceneManager.h>
#include <Core/CResCache.h>
namespace Ui {
class CWorldEditorWindow;
}
class CWorldEditorWindow : public QMainWindow
{
Q_OBJECT
CRenderer *mpRenderer;
CSceneManager *mpSceneManager;
CWorld *mpActiveWorld;
CToken mWorldToken;
CGameArea *mpActiveArea;
CToken mAreaToken;
bool mRendererInitialized;
CCamera mCamera;
ECameraMoveMode mCameraMode;
float mViewportAspectRatio;
int mViewportKeysPressed;
bool mShouldDrawSky;
void LoadScriptableLayerUI();
public:
CWorldEditorWindow(QWidget *parent);
~CWorldEditorWindow();
void InitializeWorld(CWorld *pWorld, CGameArea *pArea);
public slots:
void PaintViewport(double DeltaTime);
void SetViewportSize(int Width, int Height);
void OnViewportMouseMove(QMouseEvent *pEvent, float XMovement, float YMovement);
void OnViewportRayCast(QMouseEvent *pEvent);
void OnViewportKeyPress(QKeyEvent *pEvent);
void OnViewportKeyRelease(QKeyEvent *pEvent);
void OnViewportWheelScroll(int ScrollAmount);
private slots:
void on_actionExit_triggered();
void on_actionBackface_culling_triggered();
void on_actionWorld_triggered();
void on_actionCollision_triggered();
void on_actionObjects_triggered();
void on_actionMaterial_Animations_triggered();
void on_actionLights_triggered();
void on_actionLightingNone_triggered();
void on_actionLightingBasic_triggered();
void on_actionLightingWorld_triggered();
void on_actionSky_triggered();
void on_actionOccluder_meshes_triggered();
void on_actionDisableBloom_triggered();
void on_actionEnableBloom_triggered();
void on_actionShowBloomMaps_triggered();
signals:
void Closed();
private:
Ui::CWorldEditorWindow *ui;
void setupInstanceViewLayers();
void clearInstanceView();
void closeEvent(QCloseEvent *);
};
#endif // CWORLDEDITORWINDOW_H

460
UI/CWorldEditorWindow.ui Normal file
View File

@@ -0,0 +1,460 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CWorldEditorWindow</class>
<widget class="QMainWindow" name="CWorldEditorWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1920</width>
<height>1250</height>
</rect>
</property>
<property name="windowTitle">
<string>Prime World Editor</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="CEditorGLWidget" name="CentralGLWidget" native="true"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1920</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
<widget class="QMenu" name="menuDynamic_lighting">
<property name="title">
<string>Dynamic lighting</string>
</property>
<addaction name="actionLightingNone"/>
<addaction name="actionLightingBasic"/>
<addaction name="actionLightingWorld"/>
</widget>
<widget class="QMenu" name="menuBloom">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Bloom</string>
</property>
<addaction name="actionDisableBloom"/>
<addaction name="actionEnableBloom"/>
<addaction name="actionShowBloomMaps"/>
</widget>
<addaction name="actionReset_camera"/>
<addaction name="actionBackface_culling"/>
<addaction name="separator"/>
<addaction name="actionWorld"/>
<addaction name="actionCollision"/>
<addaction name="actionObjects"/>
<addaction name="actionMaterial_Animations"/>
<addaction name="actionLights"/>
<addaction name="actionOccluder_meshes"/>
<addaction name="actionSky"/>
<addaction name="separator"/>
<addaction name="menuDynamic_lighting"/>
<addaction name="menuBloom"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuView"/>
</widget>
<widget class="QDockWidget" name="ObjectPropertiesDock">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="floating">
<bool>false</bool>
</property>
<property name="features">
<set>QDockWidget::AllDockWidgetFeatures</set>
</property>
<property name="allowedAreas">
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Object Properties</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_5">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>294</width>
<height>654</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="ConnectionsGroup">
<property name="title">
<string>Connections</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="PropertiesGroup">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Properties</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="InstanceViewDock">
<property name="features">
<set>QDockWidget::AllDockWidgetFeatures</set>
</property>
<property name="allowedAreas">
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Instance View</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_6">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QTreeWidget" name="InstanceViewTreeWidget">
<property name="enabled">
<bool>true</bool>
</property>
<column>
<property name="text">
<string>Instance</string>
</property>
</column>
<column>
<property name="text">
<string>Type</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</widget>
<action name="actionOpen_CMDL">
<property name="text">
<string>Open CMDL</string>
</property>
</action>
<action name="actionReset_camera">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Reset camera</string>
</property>
</action>
<action name="actionBackface_culling">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Backface culling</string>
</property>
</action>
<action name="actionWorld">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>World</string>
</property>
<property name="shortcut">
<string>1</string>
</property>
</action>
<action name="actionCollision">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Collision</string>
</property>
<property name="shortcut">
<string>2</string>
</property>
</action>
<action name="actionObjects">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Objects</string>
</property>
<property name="shortcut">
<string>3</string>
</property>
</action>
<action name="actionPaths">
<property name="text">
<string>Paths</string>
</property>
</action>
<action name="actionLightmaps">
<property name="text">
<string>Lightmaps</string>
</property>
</action>
<action name="actionMaterial_Editor">
<property name="text">
<string>Material Editor</string>
</property>
</action>
<action name="actionExtract">
<property name="text">
<string>Extract</string>
</property>
</action>
<action name="actionRepack">
<property name="text">
<string>Repack</string>
</property>
</action>
<action name="actionDump_file_list">
<property name="text">
<string>Dump file list</string>
</property>
</action>
<action name="actionConvert_TXTR_to_DDS">
<property name="text">
<string>Convert TXTR to DDS</string>
</property>
</action>
<action name="actionConvert_DDS_to_TXTR">
<property name="text">
<string>Convert DDS to TXTR</string>
</property>
</action>
<action name="actionClose_all">
<property name="text">
<string>Close all</string>
</property>
</action>
<action name="actionExit">
<property name="text">
<string>Exit</string>
</property>
<property name="shortcut">
<string>Esc</string>
</property>
</action>
<action name="actionOpen_MREA">
<property name="text">
<string>Open MREA</string>
</property>
</action>
<action name="actionRead_MREA">
<property name="text">
<string>Read MREA</string>
</property>
</action>
<action name="actionMaterial_Animations">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>UV animations</string>
</property>
<property name="shortcut">
<string>4</string>
</property>
</action>
<action name="actionLights">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Lights</string>
</property>
<property name="shortcut">
<string>5</string>
</property>
</action>
<action name="actionLightingNone">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>None</string>
</property>
<property name="shortcut">
<string>Ctrl+1</string>
</property>
</action>
<action name="actionLightingBasic">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Basic</string>
</property>
<property name="shortcut">
<string>Ctrl+2</string>
</property>
</action>
<action name="actionLightingWorld">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>World lights</string>
</property>
<property name="shortcut">
<string>Ctrl+3</string>
</property>
</action>
<action name="actionSky">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Sky</string>
</property>
<property name="shortcut">
<string>7</string>
</property>
</action>
<action name="actionOccluder_meshes">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Occluder meshes</string>
</property>
<property name="shortcut">
<string>6</string>
</property>
</action>
<action name="actionDisableBloom">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>None</string>
</property>
</action>
<action name="actionEnableBloom">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Bloom</string>
</property>
</action>
<action name="actionShowBloomMaps">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Bloom Maps</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>CEditorGLWidget</class>
<extends>QWidget</extends>
<header>CEditorGLWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

24
UI/IPreviewPanel.cpp Normal file
View File

@@ -0,0 +1,24 @@
#include "IPreviewPanel.h"
#include "WScanPreviewPanel.h"
#include "WStringPreviewPanel.h"
#include "WTexturePreviewPanel.h"
IPreviewPanel::IPreviewPanel(QWidget *parent) : QFrame(parent)
{
setFrameShape(QFrame::StyledPanel);
setFrameShadow(QFrame::Plain);
setLineWidth(2);
}
// Can add more if more preview types are implemented
// Not every resource type is really suitable for this though unfortunately
IPreviewPanel* IPreviewPanel::CreatePanel(EResType Type, QWidget *pParent)
{
switch (Type)
{
case eTexture: return new WTexturePreviewPanel(pParent);
case eStringTable: return new WStringPreviewPanel(pParent);
case eScan: return new WScanPreviewPanel(pParent);
default: return nullptr;
}
}

17
UI/IPreviewPanel.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef IPREVIEWPANEL_H
#define IPREVIEWPANEL_H
#include <QFrame>
#include <Resource/CResource.h>
#include <Resource/EResType.h>
class IPreviewPanel : public QFrame
{
public:
explicit IPreviewPanel(QWidget *parent = 0);
virtual EResType ResType() = 0;
virtual void SetResource(CResource *pRes) = 0;
static IPreviewPanel* CreatePanel(EResType Type, QWidget *pParent = 0);
};
#endif // IPREVIEWPANEL_H

22
UI/PWEMaterialEditor.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef PWEMATERIALEDITOR_H
#define PWEMATERIALEDITOR_H
#include <QDialog>
namespace Ui {
class PWEMaterialEditor;
}
class PWEMaterialEditor : public QDialog
{
Q_OBJECT
public:
explicit PWEMaterialEditor(QWidget *parent = 0);
~PWEMaterialEditor();
private:
Ui::PWEMaterialEditor *ui;
};
#endif // PWEMATERIALEDITOR_H

22
UI/TestDialog.cpp Normal file
View File

@@ -0,0 +1,22 @@
#include "TestDialog.h"
#include "ui_TestDialog.h"
#include <Core/CResCache.h>
#include <iostream>
#include "WResourceSelector.h"
#include "WTextureGLWidget.h"
#include <Resource/factory/CTextureDecoder.h>
TestDialog::TestDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::TestDialog)
{
ui->setupUi(this);
CTexture *pTex = CTextureDecoder::LoadDDS(CFileInStream("E:/test2.dds", IOUtil::LittleEndian));
ui->widget->SetTexture(pTex);
}
TestDialog::~TestDialog()
{
delete ui;
}

22
UI/TestDialog.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef TESTDIALOG_H
#define TESTDIALOG_H
#include <QDialog>
namespace Ui {
class TestDialog;
}
class TestDialog : public QDialog
{
Q_OBJECT
public:
explicit TestDialog(QWidget *parent = 0);
~TestDialog();
private:
Ui::TestDialog *ui;
};
#endif // TESTDIALOG_H

125
UI/TestDialog.ui Normal file
View File

@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TestDialog</class>
<widget class="QDialog" name="TestDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<height>535</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="WRollout" name="RolloutTest" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox"/>
</item>
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="radioButton">
<property name="text">
<string>RadioButton</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton_2">
<property name="text">
<string>RadioButton</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>GroupBox</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_2">
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="WTextureGLWidget" name="widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>256</width>
<height>256</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>WRollout</class>
<extends>QWidget</extends>
<header>WRollout.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>WTextureGLWidget</class>
<extends>QWidget</extends>
<header>WTextureGLWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

46
UI/UICommon.cpp Normal file
View File

@@ -0,0 +1,46 @@
#include "UICommon.h"
// This array is intended to be used with the EResType enum
const QString gskResourceFilters[] = {
"Animation (*.ANIM)", // eAnimation
"Animation Event Data (*.EVNT)", // eAnimEventData
"Area (*.MREA)", // eArea
"Audio Metadata (*.CAUD)", // eAudioData
"Audio Group (*.AGSC)", // eAudioGrp
"Audio Sample (*.CSMP)", // eAudioSample
"Audio Stream (*.STRM)", // eAudioStream
"Audio Lookup Table (*.ATBL)", // eAudioTable
"Character (*.ANCS *.CHAR)", // eCharacter
"Collision Mesh (*.DCLN)", // eCollisionMesh
"Collision Response Data (*.CRSC)", // eCollisionResponse
"Data Dump (*.DUMB)", // eDataDump
"Decal (*.DPSC)", // eDecal
"Dependency Group (*.DGRP)", // eDependencyGroup
"Font (*.FONT)", // eFont
"GUI Frame (*.FRME)", // eGuiFrame
"Hint System Data (*.HINT)", // eHintSystem
"Invalid resource type", // eInvalid
"Area Map (*.MAPA)", // eMapArea
"World Map (*.MAPW)", // eMapWorld
"Universe Map (*.MAPU)", // eMapUniverse
"MIDI Data (*.CSNG)", // eMidi
"Model (*.CMDL)", // eModel
"Music Track (*.DSP)", // eMusicTrack
"Navigation Mesh (*.PATH)", // eNavMesh
"Pack File (*.pak)", // ePackFile
"Particle (*.PART)", // eParticle
"Electricity Particle (*.ELSC)", // eParticleElectric
"Swoosh Particle (*.SWHC)", // eParticleSwoosh
"Projectile (*.WPSC)", // eProjectile
"Invalid resource type", // eResource
"World Save Data (*.SAVW)", // eSaveWorld
"Scannable Object Info (*.SCAN)", // eScan
"Skeleton (*.CINF)", // eSkeleton
"Skin (*.CSKR)", // eSkin
"State Machine (*.AFSM *.FSM2)", // eStateMachine
"String Table (*.STRG)", // eStringTable
"Texture (*.TXTR)", // eTexture
"Tweak (*.CTWK *.ntwk)", // eTweak
"Video (*.thp)", // eVideo
"World (*.MLVL)" // eWorld
};

9
UI/UICommon.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef UICOMMON
#define UICOMMON
#include <QString>
extern const QString gskResourceFilters[];
#endif // UICOMMON

View File

@@ -0,0 +1,12 @@
#include "WCollapsibleGroupBox.h"
WCollapsibleGroupBox::WCollapsibleGroupBox()
{
}
WCollapsibleGroupBox::~WCollapsibleGroupBox()
{
}

12
UI/WCollapsibleGroupBox.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef WCOLLAPSIBLEGROUPBOX_H
#define WCOLLAPSIBLEGROUPBOX_H
class WCollapsibleGroupBox
{
public:
WCollapsibleGroupBox();
~WCollapsibleGroupBox();
};
#endif // WCOLLAPSIBLEGROUPBOX_H

92
UI/WColorPicker.cpp Normal file
View File

@@ -0,0 +1,92 @@
#include "WColorPicker.h"
#include <QPainter>
#include <QRectF>
#include <iostream>
#include <QMouseEvent>
#include <QColorDialog>
WColorPicker::WColorPicker(QWidget *parent) : QWidget(parent)
{
mColor = Qt::transparent;
}
WColorPicker::~WColorPicker()
{
}
void WColorPicker::paintEvent(QPaintEvent *)
{
QRect Area(QPoint(2,2), size() - QSize(5,5)); // Subtraction makes room for the stroke
QColor FillColor = mColor;
FillColor.setAlpha(255);
QBrush Fill(FillColor);
QPen Outline(Qt::black, 1);
QPainter Painter(this);
Painter.setBrush(Fill);
Painter.setPen(Outline);
Painter.drawRect(Area);
if (hasFocus())
{
QRect DottedLine(QPoint(0,0), size() - QSize(1,1));
Fill.setColor(Qt::transparent);
Outline.setStyle(Qt::DotLine);
Painter.setBrush(Fill);
Painter.setPen(Outline);
Painter.drawRect(DottedLine);
}
}
void WColorPicker::keyPressEvent(QKeyEvent *Event)
{
if (Event->key() == Qt::Key_Return)
{
QColorDialog ColorPick;
ColorPick.setOptions(QColorDialog::ShowAlphaChannel);
ColorPick.setCurrentColor(mColor);
int result = ColorPick.exec();
if (result)
{
mColor = ColorPick.currentColor();
emit colorChanged(mColor);
}
}
}
void WColorPicker::mousePressEvent(QMouseEvent *)
{
setFocus();
}
void WColorPicker::mouseReleaseEvent(QMouseEvent *Event)
{
if ((Event->x() < width()) && (Event->y() < height()))
{
QColorDialog ColorPick;
ColorPick.setOptions(QColorDialog::ShowAlphaChannel);
ColorPick.setCurrentColor(mColor);
int result = ColorPick.exec();
if (result)
{
mColor = ColorPick.currentColor();
emit colorChanged(mColor);
}
}
}
QColor WColorPicker::getColor()
{
return mColor;
}
void WColorPicker::setColor(QColor Color)
{
mColor = Color;
emit colorChanged(mColor);
update();
}

28
UI/WColorPicker.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef WCOLORPICKER_H
#define WCOLORPICKER_H
#include <QWidget>
#include <QColor>
class WColorPicker : public QWidget
{
Q_OBJECT
QColor mColor;
public:
explicit WColorPicker(QWidget *parent = 0);
~WColorPicker();
void paintEvent(QPaintEvent *);
void keyPressEvent(QKeyEvent *Event);
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *Event);
QColor getColor();
void setColor(QColor Color);
signals:
void colorChanged(QColor NewColor);
public slots:
};
#endif // WCOLORPICKER_H

55
UI/WDraggableSpinBox.cpp Normal file
View File

@@ -0,0 +1,55 @@
#include "WDraggableSpinBox.h"
#include <QMouseEvent>
#include <QDesktopWidget>
WDraggableSpinBox::WDraggableSpinBox(QWidget *parent) : QDoubleSpinBox(parent)
{
mBeingDragged = false;
mDefaultValue = value();
setMinimum(-1000000.0);
setMaximum(1000000.0);
setDecimals(4);
}
WDraggableSpinBox::~WDraggableSpinBox()
{
}
void WDraggableSpinBox::mousePressEvent(QMouseEvent *Event)
{
mBeingDragged = true;
mBeenDragged = false;
mInitialY = Event->y();
mInitialValue = value();
}
void WDraggableSpinBox::mouseReleaseEvent(QMouseEvent *Event)
{
mBeingDragged = false;
if (Event->button() == Qt::LeftButton)
{
if (!mBeenDragged)
{
if (Event->y() <= height() / 2)
stepUp();
else
stepDown();
}
}
else if (Event->button() == Qt::RightButton)
{
setValue(mDefaultValue);
}
}
void WDraggableSpinBox::mouseMoveEvent(QMouseEvent *Event)
{
if (mBeingDragged)
{
double DragAmount = (singleStep() / 10.0) * (mInitialY - Event->y());
setValue(mInitialValue + DragAmount);
if (DragAmount != 0) mBeenDragged = true;
}
}

23
UI/WDraggableSpinBox.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef WDRAGGABLESPINBOX_H
#define WDRAGGABLESPINBOX_H
#include <QDoubleSpinBox>
class WDraggableSpinBox : public QDoubleSpinBox
{
Q_OBJECT
bool mBeingDragged;
bool mBeenDragged;
double mInitialValue;
double mDefaultValue;
int mInitialY;
public:
explicit WDraggableSpinBox(QWidget *parent = 0);
~WDraggableSpinBox();
void mousePressEvent(QMouseEvent *Event);
void mouseReleaseEvent(QMouseEvent *Event);
void mouseMoveEvent(QMouseEvent *Event);
};
#endif // WDRAGGABLESPINBOX_H

353
UI/WPropertyEditor.cpp Normal file
View File

@@ -0,0 +1,353 @@
#include "WPropertyEditor.h"
#include "WDraggableSpinBox.h"
#include "WResourceSelector.h"
#include "WColorPicker.h"
#include "WVectorEditor.h"
#include <QCheckBox>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QLineEdit>
#include <QGroupBox>
#include <QFontMetrics>
static const QString gskNullProperty = "[NULL]";
static const QString gskUnsupportedType = "Invalid property type";
WPropertyEditor::WPropertyEditor(QWidget *pParent, CPropertyBase *pProperty)
: QWidget(pParent)
{
mUI.PropertyName = new QLabel(gskNullProperty, this);
mUI.EditorWidget = nullptr;
mUI.Layout = new QHBoxLayout(this);
mUI.Layout->addWidget(mUI.PropertyName);
mUI.Layout->setContentsMargins(0,0,0,0);
setLayout(mUI.Layout);
mpProperty = nullptr;
SetProperty(pProperty);
}
WPropertyEditor::~WPropertyEditor()
{
}
void WPropertyEditor::resizeEvent(QResizeEvent *pEvent)
{
CreateLabelText();
}
void WPropertyEditor::SetProperty(CPropertyBase *pProperty)
{
if (pProperty)
{
bool IsNewProperty = ((!mpProperty) || (pProperty->Template() != mpProperty->Template()));
mpProperty = pProperty;
if (IsNewProperty)
CreateEditor();
else
UpdateEditor();
}
else
{
delete mUI.EditorWidget;
mUI.EditorWidget = nullptr;
mpProperty = pProperty;
mUI.PropertyName->setText(gskNullProperty);
}
}
void WPropertyEditor::CreateEditor()
{
// Clear existing edit widget (if any)
delete mUI.EditorWidget;
// Set name
mUI.PropertyName->setText(QString::fromStdString(mpProperty->Name()));
mUI.PropertyName->setToolTip(QString::fromStdString(mpProperty->Name()));
// Set editor widget
switch (mpProperty->Type())
{
// Bool - QCheckBox
case eBoolProperty:
{
CBoolProperty *pBoolCast = static_cast<CBoolProperty*>(mpProperty);
QCheckBox *pCheckBox = new QCheckBox(this);
pCheckBox->setChecked(pBoolCast->Get());
mUI.EditorWidget = pCheckBox;
break;
}
// Byte - QSpinBox
case eByteProperty:
{
CByteProperty *pByteCast = static_cast<CByteProperty*>(mpProperty);
QSpinBox *pSpinBox = new QSpinBox(this);
pSpinBox->setRange(-128, 128);
pSpinBox->setValue(pByteCast->Get());
mUI.EditorWidget = pSpinBox;
break;
}
// Short - QSpinBox
case eShortProperty:
{
CShortProperty *pShortCast = static_cast<CShortProperty*>(mpProperty);
QSpinBox *pSpinBox = new QSpinBox(this);
pSpinBox->setRange(-32768, 32767);
pSpinBox->setValue(pShortCast->Get());
mUI.EditorWidget = pSpinBox;
break;
}
// Long - QSpinBox
case eLongProperty:
{
CLongProperty *pLongCast = static_cast<CLongProperty*>(mpProperty);
QSpinBox *pSpinBox = new QSpinBox(this);
pSpinBox->setRange(-2147483648, 2147483647);
pSpinBox->setValue(pLongCast->Get());
mUI.EditorWidget = pSpinBox;
break;
}
// Float - WDraggableSpinBox
case eFloatProperty:
{
CFloatProperty *pFloatCast = static_cast<CFloatProperty*>(mpProperty);
WDraggableSpinBox *pDraggableSpinBox = new WDraggableSpinBox(this);
pDraggableSpinBox->setValue(pFloatCast->Get());
mUI.EditorWidget = pDraggableSpinBox;
break;
}
// String - QLineEdit
case eStringProperty:
{
CStringProperty *pStringCast = static_cast<CStringProperty*>(mpProperty);
QLineEdit *pLineEdit = new QLineEdit(this);
pLineEdit->setText(QString::fromStdString(pStringCast->Get()));
pLineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
pLineEdit->setCursorPosition(0);
mUI.EditorWidget = pLineEdit;
break;
}
// Vector3 - WVectorEditor
case eVector3Property:
{
CVector3Property *pVector3Cast = static_cast<CVector3Property*>(mpProperty);
WVectorEditor *pVectorEditor = new WVectorEditor(this);
pVectorEditor->SetValue(pVector3Cast->Get());
pVectorEditor->SetText(QString::fromStdString(mpProperty->Name()));
mUI.PropertyName->hide();
mUI.EditorWidget = pVectorEditor;
break;
}
// Color - WColorPicker
case eColorProperty:
{
CColorProperty *pColorCast = static_cast<CColorProperty*>(mpProperty);
WColorPicker *pColorPicker = new WColorPicker(this);
CColor color = pColorCast->Get();
QColor qcolor = QColor(color.r, color.g, color.b, color.a);
pColorPicker->setColor(qcolor);
mUI.EditorWidget = pColorPicker;
break;
}
// Enum - todo (will be QComboBox)
case eEnumProperty:
mUI.EditorWidget = new QLabel("[placeholder]", this);
break;
// File - WResourceSelector
case eFileProperty:
{
CFileProperty *pFileCast = static_cast<CFileProperty*>(mpProperty);
WResourceSelector *pResourceSelector = new WResourceSelector(this);
pResourceSelector->AdjustPreviewToParent(true);
pResourceSelector->SetResource(pFileCast->Get());
mUI.EditorWidget = pResourceSelector;
break;
}
// Struct - QGroupBox
case eStructProperty:
{
CPropertyStruct *pStructCast = static_cast<CPropertyStruct*>(mpProperty);
QGroupBox *pGroupBox = new QGroupBox(this);
QVBoxLayout *pStructLayout = new QVBoxLayout(pGroupBox);
pGroupBox->setLayout(pStructLayout);
pGroupBox->setTitle(QString::fromStdString(pStructCast->Name()));
mUI.PropertyName->hide();
for (u32 p = 0; p < pStructCast->Count(); p++)
{
WPropertyEditor *pEditor = new WPropertyEditor(pGroupBox, pStructCast->PropertyByIndex(p));
pStructLayout->addWidget(pEditor);
}
mUI.EditorWidget = pGroupBox;
break;
}
// Invalid
case eInvalidProperty:
default:
mUI.EditorWidget = new QLabel(gskUnsupportedType, this);
break;
}
// For some reason setting a minimum size on group boxes flattens it...
if ((mpProperty->Type() != eStructProperty) && (mpProperty->Type() != eVector3Property))
{
mUI.EditorWidget->setMinimumHeight(21);
mUI.EditorWidget->setMaximumHeight(21);
}
mUI.Layout->addWidget(mUI.EditorWidget, 0);
CreateLabelText();
}
void WPropertyEditor::UpdateEditor()
{
switch (mpProperty->Type())
{
case eBoolProperty:
{
CBoolProperty *pBoolCast = static_cast<CBoolProperty*>(mpProperty);
QCheckBox *pCheckBox = static_cast<QCheckBox*>(mUI.EditorWidget);
pCheckBox->setChecked(pBoolCast->Get());
break;
}
case eByteProperty:
{
CByteProperty *pByteCast = static_cast<CByteProperty*>(mpProperty);
QSpinBox *pSpinBox = static_cast<QSpinBox*>(mUI.EditorWidget);
pSpinBox->setValue(pByteCast->Get());
break;
}
case eShortProperty:
{
CShortProperty *pShortCast = static_cast<CShortProperty*>(mpProperty);
QSpinBox *pSpinBox = static_cast<QSpinBox*>(mUI.EditorWidget);
pSpinBox->setValue(pShortCast->Get());
break;
}
case eLongProperty:
{
CLongProperty *pLongCast = static_cast<CLongProperty*>(mpProperty);
QSpinBox *pSpinBox = static_cast<QSpinBox*>(mUI.EditorWidget);
pSpinBox->setValue(pLongCast->Get());
break;
}
case eFloatProperty:
{
CFloatProperty *pFloatCast = static_cast<CFloatProperty*>(mpProperty);
WDraggableSpinBox *pDraggableSpinBox = static_cast<WDraggableSpinBox*>(mUI.EditorWidget);
pDraggableSpinBox->setValue(pFloatCast->Get());
break;
}
case eStringProperty:
{
CStringProperty *pStringCast = static_cast<CStringProperty*>(mpProperty);
QLineEdit *pLineEdit = static_cast<QLineEdit*>(mUI.EditorWidget);
pLineEdit->setText(QString::fromStdString(pStringCast->Get()));
pLineEdit->setCursorPosition(0);
break;
}
case eVector3Property:
{
CVector3Property *pVector3Cast = static_cast<CVector3Property*>(mpProperty);
WVectorEditor *pVectorEditor = static_cast<WVectorEditor*>(mUI.EditorWidget);
pVectorEditor->SetValue(pVector3Cast->Get());
break;
}
case eColorProperty:
{
CColorProperty *pColorCast = static_cast<CColorProperty*>(mpProperty);
WColorPicker *pColorPicker = static_cast<WColorPicker*>(mUI.EditorWidget);
CColor color = pColorCast->Get();
QColor qcolor = QColor(color.r, color.g, color.b, color.a);
pColorPicker->setColor(qcolor);
break;
}
case eEnumProperty:
break;
case eFileProperty:
{
CFileProperty *pFileCast = static_cast<CFileProperty*>(mpProperty);
WResourceSelector *pResourceSelector = static_cast<WResourceSelector*>(mUI.EditorWidget);
pResourceSelector->SetResource(pFileCast->Get());
break;
}
case eStructProperty:
{
CPropertyStruct *pStructCast = static_cast<CPropertyStruct*>(mpProperty);
QGroupBox *pGroupBox = static_cast<QGroupBox*>(mUI.EditorWidget);
QObjectList ChildList = pGroupBox->children();
u32 PropNum = 0;
foreach (QObject *pObj, ChildList)
{
if (pObj != pGroupBox->layout())
{
CPropertyBase *pProp = pStructCast->PropertyByIndex(PropNum);
static_cast<WPropertyEditor*>(pObj)->SetProperty(pProp);
PropNum++;
}
}
break;
}
}
}
void WPropertyEditor::CreateLabelText()
{
mUI.PropertyName->setText(QString::fromStdString(mpProperty->Name()));
QFontMetrics metrics(mUI.PropertyName->font());
QString text = metrics.elidedText(QString::fromStdString(mpProperty->Name()), Qt::ElideRight, mUI.PropertyName->width());
mUI.PropertyName->setText(text);
}

36
UI/WPropertyEditor.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef WPROPERTYEDITOR_H
#define WPROPERTYEDITOR_H
#include <QWidget>
#include <QHBoxLayout>
#include <QLabel>
#include <Resource/script/CProperty.h>
class WPropertyEditor : public QWidget
{
Q_OBJECT
// Editor
CPropertyBase *mpProperty;
// UI
struct {
QLabel *PropertyName;
QWidget *EditorWidget;
QHBoxLayout *Layout;
} mUI;
public:
explicit WPropertyEditor(QWidget *pParent = 0, CPropertyBase *pProperty = 0);
~WPropertyEditor();
void resizeEvent(QResizeEvent *pEvent);
void SetProperty(CPropertyBase *pProperty);
private:
void CreateEditor();
void UpdateEditor();
void CreateLabelText();
};
#endif // WPROPERTYEDITOR_H

335
UI/WResourceSelector.cpp Normal file
View File

@@ -0,0 +1,335 @@
#include "WResourceSelector.h"
#include "UICommon.h"
#include "WTexturePreviewPanel.h"
#include <Core/CResCache.h>
#include <QApplication>
#include <QCompleter>
#include <QDesktopWidget>
#include <QDirModel>
#include <QEvent>
#include <QFileDialog>
WResourceSelector::WResourceSelector(QWidget *parent) : QWidget(parent)
{
// Initialize Members
mHasMultipleExtensions = false;
mShowEditButton = false;
mShowExportButton = false;
mpPreviewPanel = nullptr;
mEnablePreviewPanel = true;
mPreviewPanelValid = false;
mShowingPreviewPanel = false;
mAdjustPreviewToParent = false;
mpResource = nullptr;
mResType = eInvalidResType;
// Create Widgets
mUI.LineEdit = new QLineEdit(this);
mUI.BrowseButton = new QPushButton(this);
mUI.EditButton = new QPushButton("Edit", this);
mUI.ExportButton = new QPushButton("Export", this);
// Create Layout
mUI.Layout = new QHBoxLayout(this);
setLayout(mUI.Layout);
mUI.Layout->addWidget(mUI.LineEdit);
mUI.Layout->addWidget(mUI.BrowseButton);
mUI.Layout->addWidget(mUI.EditButton);
mUI.Layout->addWidget(mUI.ExportButton);
mUI.Layout->setContentsMargins(0,0,0,0);
mUI.Layout->setSpacing(1);
// Set Up Widgets
mUI.LineEdit->installEventFilter(this);
mUI.LineEdit->setMouseTracking(true);
mUI.LineEdit->setMaximumHeight(23);
mUI.LineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
mUI.BrowseButton->installEventFilter(this);
mUI.BrowseButton->setMouseTracking(true);
mUI.BrowseButton->setText("...");
mUI.BrowseButton->setMaximumSize(25, 23);
mUI.BrowseButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
mUI.EditButton->installEventFilter(this);
mUI.EditButton->setMouseTracking(true);
mUI.EditButton->setMaximumSize(50, 23);
mUI.EditButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
mUI.EditButton->hide();
mUI.ExportButton->installEventFilter(this);
mUI.ExportButton->setMouseTracking(true);
mUI.ExportButton->setMaximumSize(50, 23);
mUI.ExportButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
mUI.ExportButton->hide();
QCompleter *pCompleter = new QCompleter(this);
pCompleter->setModel(new QDirModel(pCompleter));
mUI.LineEdit->setCompleter(pCompleter);
connect(mUI.LineEdit, SIGNAL(editingFinished()), this, SLOT(OnLineEditTextEdited()));
connect(mUI.BrowseButton, SIGNAL(clicked()), this, SLOT(OnBrowseButtonClicked()));
}
WResourceSelector::~WResourceSelector()
{
delete mpPreviewPanel;
}
bool WResourceSelector::event(QEvent *pEvent)
{
if ((pEvent->type() == QEvent::Leave) || (pEvent->type() == QEvent::WindowDeactivate))
HidePreviewPanel();
return false;
}
bool WResourceSelector::eventFilter(QObject *pObj, QEvent *pEvent)
{
if (pEvent->type() == QEvent::MouseMove)
if (mEnablePreviewPanel)
ShowPreviewPanel();
return false;
}
// ************ GETTERS ************
EResType WResourceSelector::GetResType()
{
return mResType;
}
QString WResourceSelector::GetText()
{
return mUI.LineEdit->text();
}
bool WResourceSelector::IsEditButtonEnabled()
{
return mShowEditButton;
}
bool WResourceSelector::IsExportButtonEnabled()
{
return mShowExportButton;
}
bool WResourceSelector::IsPreviewPanelEnabled()
{
return mEnablePreviewPanel;
}
// ************ SETTERS ************
void WResourceSelector::SetResource(CResource *pRes)
{
mpResource = pRes;
mResToken = CToken(pRes);
if (pRes)
{
CFourCC ext = StringUtil::GetExtension(pRes->Source());
mResType = CResource::ResTypeForExtension(ext);
mUI.LineEdit->setText(QString::fromStdString(pRes->Source()));
}
else
{
mResType = eInvalidResType;
mUI.LineEdit->clear();
}
CreatePreviewPanel();
SetButtonsBasedOnResType();
}
void WResourceSelector::SetResType(EResType Type)
{
mResType = Type;
mpResource = nullptr;
mResToken.Unlock();
mUI.LineEdit->clear();
CreatePreviewPanel();
SetButtonsBasedOnResType();
}
void WResourceSelector::SetResTypes(const CStringList &ExtensionList)
{
}
void WResourceSelector::SetText(const QString& ResPath)
{
mUI.LineEdit->setText(ResPath);
LoadResource(ResPath);
}
void WResourceSelector::SetEditButtonEnabled(bool Enabled)
{
mShowEditButton = Enabled;
if (Enabled) mUI.EditButton->show();
else mUI.EditButton->hide();
}
void WResourceSelector::SetExportButtonEnabled(bool Enabled)
{
mShowExportButton = Enabled;
if (Enabled) mUI.ExportButton->show();
else mUI.ExportButton->hide();
}
void WResourceSelector::SetPreviewPanelEnabled(bool Enabled)
{
mEnablePreviewPanel = Enabled;
if (!mPreviewPanelValid) CreatePreviewPanel();
}
void WResourceSelector::AdjustPreviewToParent(bool adjust)
{
mAdjustPreviewToParent = adjust;
}
// ************ SLOTS ************
void WResourceSelector::OnLineEditTextEdited()
{
LoadResource(mUI.LineEdit->text());
}
void WResourceSelector::OnBrowseButtonClicked()
{
QString Filter = gskResourceFilters[mResType];
std::string ResTypeStr = Filter.toStdString();
size_t EndName = ResTypeStr.find_last_of("(") - 1;
ResTypeStr = ResTypeStr.substr(0, EndName);
QString ResType = QString::fromStdString(ResTypeStr);
QString NewRes = QFileDialog::getOpenFileName(this, "Select " + ResType, "", Filter);
if (!NewRes.isEmpty())
{
mUI.LineEdit->setText(NewRes);
LoadResource(NewRes);
}
}
void WResourceSelector::OnEditButtonClicked()
{
Edit();
}
void WResourceSelector::OnExportButtonClicked()
{
Export();
}
// ************ PRIVATE ************
// Should the resource selector handle edit/export itself
// or delegate it entirely to the signals?
void WResourceSelector::Edit()
{
emit EditResource(mpResource);
}
void WResourceSelector::Export()
{
emit ExportResource(mpResource);
}
void WResourceSelector::CreatePreviewPanel()
{
delete mpPreviewPanel;
mpPreviewPanel = IPreviewPanel::CreatePanel(mResType, this);
if (!mpPreviewPanel) mPreviewPanelValid = false;
else
{
mPreviewPanelValid = true;
mpPreviewPanel->setWindowFlags(Qt::ToolTip);
if (mpResource) mpPreviewPanel->SetResource(mpResource);
}
}
void WResourceSelector::ShowPreviewPanel()
{
if ((mPreviewPanelValid) && (mpResource != nullptr))
{
// Preferred panel point is lower-right, but can move if there's not enough room
QPoint Position = parentWidget()->mapToGlobal(pos());
QRect ScreenResolution = QApplication::desktop()->screenGeometry();
QSize PanelSize = mpPreviewPanel->size();
QPoint PanelPoint = Position;
// Calculate parent adjustment with 9 pixels of buffer
int ParentAdjustLeft = (mAdjustPreviewToParent ? pos().x() + 9 : 0);
int ParentAdjustRight = (mAdjustPreviewToParent ? parentWidget()->width() - pos().x() + 9 : 0);
// Is there enough space on the right?
if (Position.x() + width() + PanelSize.width() + ParentAdjustRight >= ScreenResolution.width())
PanelPoint.rx() -= PanelSize.width() + ParentAdjustLeft;
else
PanelPoint.rx() += width() + ParentAdjustRight;
// Is there enough space on the bottom?
if (Position.y() + PanelSize.height() >= ScreenResolution.height() - 30)
{
int Difference = Position.y() + PanelSize.height() - ScreenResolution.height() + 30;
PanelPoint.ry() -= Difference;
}
mpPreviewPanel->move(PanelPoint);
mpPreviewPanel->show();
mShowingPreviewPanel = true;
}
}
void WResourceSelector::HidePreviewPanel()
{
if (mPreviewPanelValid && mShowingPreviewPanel)
{
mpPreviewPanel->hide();
mShowingPreviewPanel = false;
}
}
void WResourceSelector::LoadResource(const QString& ResPath)
{
mpResource = nullptr;
mResToken.Unlock();
if ((mResType != eArea) && (mResType != eWorld))
{
std::string PathStr = ResPath.toStdString();
CFourCC ResExt = StringUtil::GetExtension(PathStr).c_str();
if (CResource::ResTypeForExtension(ResExt) == mResType)
{
mpResource = gResCache.GetResource(PathStr);
mResToken = CToken(mpResource);
if (mPreviewPanelValid) mpPreviewPanel->SetResource(mpResource);
}
}
emit ResourceChanged(ResPath);
}
void WResourceSelector::SetButtonsBasedOnResType()
{
// Basically this function sets whether the "Export" and "Edit"
// buttons are present based on the resource type.
switch (mResType)
{
// Export button should be enabled here because CTexture already has a DDS export function
// However, need to figure out what sort of interface to create to do it. Disabling until then.
case eTexture:
SetEditButtonEnabled(false);
SetExportButtonEnabled(false);
break;
default:
SetEditButtonEnabled(false);
SetExportButtonEnabled(false);
break;
}
}

91
UI/WResourceSelector.h Normal file
View File

@@ -0,0 +1,91 @@
#ifndef WRESOURCESELECTOR_H
#define WRESOURCESELECTOR_H
#include "IPreviewPanel.h"
#include <Common/CFourCC.h>
#include <Core/CToken.h>
#include <Resource/EResType.h>
#include <QLabel>
#include <QString>
#include <QLineEdit>
#include <QPushButton>
#include <QHBoxLayout>
class WResourceSelector : public QWidget
{
Q_OBJECT
// Selector
QStringList mSupportedExtensions;
bool mHasMultipleExtensions;
bool mShowEditButton;
bool mShowExportButton;
// Preview Panel
IPreviewPanel *mpPreviewPanel;
bool mEnablePreviewPanel;
bool mPreviewPanelValid;
bool mShowingPreviewPanel;
bool mAdjustPreviewToParent;
// Resource
CResource *mpResource;
CToken mResToken;
EResType mResType;
// UI
struct {
QLineEdit *LineEdit;
QPushButton *BrowseButton;
QPushButton *ExportButton;
QPushButton *EditButton;
QHBoxLayout *Layout;
} mUI;
signals:
void ResourceChanged(const QString& NewResPath);
void EditResource(CResource *pRes);
void ExportResource(CResource *pRes);
public:
explicit WResourceSelector(QWidget *parent = 0);
~WResourceSelector();
bool event(QEvent *);
bool eventFilter(QObject *, QEvent *);
// Getters
EResType GetResType();
QString GetText();
bool IsEditButtonEnabled();
bool IsExportButtonEnabled();
bool IsPreviewPanelEnabled();
// Setters
void SetResource(CResource *pRes);
void SetResType(EResType Type);
void SetResTypes(const CStringList& ExtensionList);
void SetText(const QString& ResPath);
void SetEditButtonEnabled(bool Enabled);
void SetExportButtonEnabled(bool Enabled);
void SetPreviewPanelEnabled(bool Enabled);
void AdjustPreviewToParent(bool adjust);
// Slots
public slots:
void OnLineEditTextEdited();
void OnBrowseButtonClicked();
void OnEditButtonClicked();
void OnExportButtonClicked();
private:
void Edit();
void Export();
void CreatePreviewPanel();
void ShowPreviewPanel();
void HidePreviewPanel();
void LoadResource(const QString& ResPath);
void SetButtonsBasedOnResType();
};
#endif // WRESOURCESELECTOR_H

64
UI/WRollout.cpp Normal file
View File

@@ -0,0 +1,64 @@
#include "WRollout.h"
#include <QApplication>
#include <QBrush>
#include <QPainter>
#include <QPen>
#include <QRect>
#include <QVBoxLayout>
WRollout::WRollout(QWidget *parent) : QWidget(parent)
{
this->setContentsMargins(10, 20, 10, 10);
}
WRollout::~WRollout()
{
}
void WRollout::setCollapsed(bool collapsed)
{
mCollapsed = collapsed;
}
bool WRollout::isCollapsed()
{
return mCollapsed;
}
void WRollout::setName(const QString& name)
{
mpTopButton->setText(name);
}
QString WRollout::getName()
{
return mpTopButton->text();
}
void WRollout::paintEvent(QPaintEvent *)
{
QPainter Painter(this);
// Draw box
QPen Pen;
Pen.setColor(Qt::white);
Painter.setPen(Pen);
QBrush Brush;
Brush.setColor(Qt::white);
Painter.setBrush(Brush);
int AreaBoxTop = (mCollapsed) ? 7 : 10;
QRect Area(QPoint(0,AreaBoxTop), size() - QSize(Pen.width(), Pen.width() + AreaBoxTop));
Painter.drawRoundedRect(Area, 5.f, 5.f);
// Draw button
QRect TopButton(QPoint(10,0), QSize(width() - 20, 21));
QPalette Palette = qApp->palette();
Painter.setBrush(Palette.color(QPalette::Text));
Painter.drawRect(TopButton);
}
void WRollout::resizeEvent(QResizeEvent *)
{
}

29
UI/WRollout.h Normal file
View File

@@ -0,0 +1,29 @@
#ifndef WROLLOUT_H
#define WROLLOUT_H
#include <QPushButton>
#include <QWidget>
class WRollout : public QWidget
{
Q_PROPERTY(bool mCollapsed READ isCollapsed WRITE setCollapsed)
QPushButton *mpTopButton;
QWidget *mpContainerWidget;
bool mCollapsed;
public:
explicit WRollout(QWidget *parent = 0);
~WRollout();
void setCollapsed(bool collapsed);
bool isCollapsed();
void setName(const QString& name);
QString getName();
void paintEvent(QPaintEvent *);
void resizeEvent(QResizeEvent *);
private:
bool mouseInButton(int x, int y);
};
#endif // WROLLOUT_H

75
UI/WScanPreviewPanel.cpp Normal file
View File

@@ -0,0 +1,75 @@
#include "WScanPreviewPanel.h"
#include "ui_WScanPreviewPanel.h"
#include "WStringPreviewPanel.h"
#include <Resource/CScan.h>
WScanPreviewPanel::WScanPreviewPanel(QWidget *parent) :
IPreviewPanel(parent),
ui(new Ui::WScanPreviewPanel)
{
ui->setupUi(this);
ui->ScanTextWidget->setFrameShape(QFrame::NoFrame);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum );
}
WScanPreviewPanel::~WScanPreviewPanel()
{
delete ui;
}
EResType WScanPreviewPanel::ResType()
{
return eScan;
}
void WScanPreviewPanel::SetResource(CResource *pRes)
{
// Clear existing UI
ui->ScanTypeLabel->clear();
ui->ScanSpeedLabel->clear();
ui->ScanCategoryLabel->clear();
// Set up new UI
if (pRes->Type() == eScan)
{
CScan *pScan = static_cast<CScan*>(pRes);
// Scan type
if (pScan->IsImportant())
ui->ScanTypeLabel->setText("<b><font color=\"red\">Important</font></b>");
else
ui->ScanTypeLabel->setText("<b><font color=\"orange\">Normal</font></b>");
// Scan speed
if (pScan->IsSlow())
ui->ScanSpeedLabel->setText("<b><font color=\"blue\">Slow</font></b>");
else
ui->ScanSpeedLabel->setText("<b><font color=\"green\">Fast</font></b>");
// Scan category
switch (pScan->LogbookCategory())
{
case CScan::eNone:
ui->ScanCategoryLabel->setText("<b>None</b>");
break;
case CScan::eChozoLore:
ui->ScanCategoryLabel->setText("<b>Chozo Lore</b>");
break;
case CScan::ePirateData:
ui->ScanCategoryLabel->setText("<b>Pirate Data</b>");
break;
case CScan::eCreatures:
ui->ScanCategoryLabel->setText("<b>Creatures</b>");
break;
case CScan::eResearch:
ui->ScanCategoryLabel->setText("<b>Research</b>");
break;
}
// Scan text
ui->ScanTextWidget->SetResource(pScan->ScanText());
}
else
ui->ScanTextWidget->SetResource(nullptr);
}

24
UI/WScanPreviewPanel.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef WSCANPREVIEWPANEL_H
#define WSCANPREVIEWPANEL_H
#include "IPreviewPanel.h"
namespace Ui {
class WScanPreviewPanel;
}
class WScanPreviewPanel : public IPreviewPanel
{
Q_OBJECT
public:
explicit WScanPreviewPanel(QWidget *parent = 0);
~WScanPreviewPanel();
EResType ResType();
void SetResource(CResource *pRes);
private:
Ui::WScanPreviewPanel *ui;
};
#endif // WSCANPREVIEWPANEL_H

154
UI/WScanPreviewPanel.ui Normal file
View File

@@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WScanPreviewPanel</class>
<widget class="QWidget" name="WScanPreviewPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>114</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="TypeInfoLabel">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="ScanTypeLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="SpeedInfoLabel">
<property name="text">
<string>Speed:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="ScanSpeedLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="LogbookInfoLabel">
<property name="text">
<string>Logbook:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="ScanCategoryLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="WStringPreviewPanel" name="ScanTextWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>WStringPreviewPanel</class>
<extends>QWidget</extends>
<header>WStringPreviewPanel.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,52 @@
#include "WStringPreviewPanel.h"
#include <QFontMetrics>
#include <QTextLayout>
#include <Resource/CStringTable.h>
WStringPreviewPanel::WStringPreviewPanel(QWidget *pParent) : IPreviewPanel(pParent)
{
mpTextLabel = new QLabel(this);
mpTextLabel->setWordWrap(true);
mpLayout = new QVBoxLayout(this);
mpLayout->setAlignment(Qt::AlignTop);
mpLayout->addWidget(mpTextLabel);
setLayout(mpLayout);
QFontMetrics metrics(mpTextLabel->font());
this->resize(400, 100);
this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
}
WStringPreviewPanel::~WStringPreviewPanel()
{
}
EResType WStringPreviewPanel::ResType()
{
return eStringTable;
}
void WStringPreviewPanel::SetResource(CResource *pRes)
{
mpTextLabel->clear();
if ((pRes) && (pRes->Type() == eStringTable))
{
CStringTable *pString = static_cast<CStringTable*>(pRes);
QString text;
// Build text string using first four strings from table (or less if there aren't 4)
u32 numStrings = (pString->GetStringCount() < 4 ? pString->GetStringCount() : 4);
for (u32 iStr = 0; iStr < numStrings; iStr++)
{
text += QString::fromStdWString(pString->GetString(0, iStr));
text += "\n";
}
// Build text layout to determine where to elide the label
QTextLayout layout(text);
mpTextLabel->setText(text);
}
}

24
UI/WStringPreviewPanel.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef WSTRINGPREVIEWPANEL_H
#define WSTRINGPREVIEWPANEL_H
#include "IPreviewPanel.h"
#include <QLabel>
#include <QVBoxLayout>
#include <QSpacerItem>
class WStringPreviewPanel : public IPreviewPanel
{
Q_OBJECT
QLabel *mpTextLabel;
QVBoxLayout *mpLayout;
QSpacerItem *mpSpacer;
public:
explicit WStringPreviewPanel(QWidget *pParent = 0);
~WStringPreviewPanel();
EResType ResType();
void SetResource(CResource *pRes);
};
#endif // WSTRINGPREVIEWPANEL_H

156
UI/WTextureGLWidget.cpp Normal file
View File

@@ -0,0 +1,156 @@
#include "WTextureGLWidget.h"
#include <Core/CDrawUtil.h>
#include <Core/CGraphics.h>
#include <Common/CTransform4f.h>
#include <Common/AnimUtil.h>
#include <Core/CResCache.h>
#include <iostream>
#include <iomanip>
WTextureGLWidget::WTextureGLWidget(QWidget *parent, CTexture *pTex) : QOpenGLWidget(parent)
{
SetTexture(pTex);
mInitialized = false;
}
WTextureGLWidget::~WTextureGLWidget()
{
if (mInitialized) CGraphics::ReleaseContext(mContextID);
}
void WTextureGLWidget::initializeGL()
{
CGraphics::Initialize();
glEnable(GL_BLEND);
mContextID = CGraphics::GetContextIndex();
mInitialized = true;
}
void WTextureGLWidget::paintGL()
{
CGraphics::SetActiveContext(mContextID);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(1.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
// Set matrices to identity
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
CGraphics::sMVPBlock.ViewMatrix = CMatrix4f::skIdentity;
CGraphics::sMVPBlock.ProjectionMatrix = CMatrix4f::skIdentity;
CGraphics::UpdateMVPBlock();
// Draw checkerboard background
CDrawUtil::UseTextureShader();
glDepthMask(GL_FALSE);
CDrawUtil::LoadCheckerboardTexture(0);
CDrawUtil::DrawSquare(&mCheckerCoords[0].x);
// Make it darker
CDrawUtil::UseColorShader(CColor((u8) 0, 0, 0, 128));
glDepthMask(GL_FALSE);
CDrawUtil::DrawSquare();
// Leave it at just the checkerboard if there's no texture
if (!mpTexture) return;
// Draw texture
CDrawUtil::UseTextureShader();
mpTexture->Bind(0);
CGraphics::sMVPBlock.ModelMatrix = mTexTransform.ToMatrix4f();
CGraphics::UpdateMVPBlock();
CDrawUtil::DrawSquare();
glEnable(GL_DEPTH_TEST);
}
void WTextureGLWidget::resizeGL(int w, int h)
{
mAspectRatio = (float) w / (float) h;
glViewport(0, 0, w, h);
CalcTexTransform();
CalcCheckerCoords();
update();
}
void WTextureGLWidget::SetTexture(CTexture *pTex)
{
mpTexture = pTex;
mTexToken = CToken(pTex);
if (pTex) mTexAspectRatio = (float) pTex->Width() / (float) pTex->Height();
else mTexAspectRatio = 0.f;
CalcTexTransform();
CalcCheckerCoords();
update();
}
void WTextureGLWidget::CalcTexTransform()
{
// This is a simple scale based on the dimensions of the viewport, in order to
// avoid stretching the texture if it doesn't match the viewport aspect ratio.
mTexTransform = CTransform4f::skIdentity;
float Diff = mTexAspectRatio / mAspectRatio;
if (mAspectRatio >= mTexAspectRatio)
mTexTransform.Scale(Diff, 1.f, 1.f);
else
mTexTransform.Scale(1.f, 1.f / Diff, 1.f);
}
void WTextureGLWidget::CalcCheckerCoords()
{
// The translation vector is set up so the checkerboard stays centered on the screen
// rather than expanding from the bottom-left corner. This makes it look more natural.
CVector2f Trans;
float InvAspect = (mAspectRatio == 0.f) ? 0.f : 1.f / mAspectRatio;
float InvTexAspect = (mTexAspectRatio == 0.f) ? 0.f : 1.f / mTexAspectRatio;
float XBase, YBase, XScale, YScale;
// Horizontal texture
if ((mpTexture != nullptr) && (mpTexture->Width() > mpTexture->Height()))
{
XBase = 1.f;
YBase = InvTexAspect;
XScale = InvTexAspect;
YScale = 1.f;
}
// Vertical texture
else
{
XBase = mTexAspectRatio;
YBase = 1.f;
XScale = 1.f;
YScale = mTexAspectRatio;
}
// Space on left/right
if (mAspectRatio > mTexAspectRatio)
{
Trans = CVector2f(mAspectRatio / 2.f, 0.5f) * -XScale;
mCheckerCoords[0] = CVector2f(0.f, YBase);
mCheckerCoords[1] = CVector2f(mAspectRatio * XScale, YBase);
mCheckerCoords[2] = CVector2f(mAspectRatio * XScale, 0.f);
mCheckerCoords[3] = CVector2f(0.f, 0.f);
}
// Space on top/bottom
else
{
Trans = CVector2f(0.5f, InvAspect / 2.f) * -YScale;
mCheckerCoords[0] = CVector2f(0.f, InvAspect * YScale);
mCheckerCoords[1] = CVector2f(XBase, InvAspect * YScale);
mCheckerCoords[2] = CVector2f(XBase, 0.f);
mCheckerCoords[3] = CVector2f(0.f, 0.f);
}
// Finally, apply translation/scale
for (u32 iCoord = 0; iCoord < 4; iCoord++)
{
mCheckerCoords[iCoord] += Trans;
mCheckerCoords[iCoord] *= 10.f;
}
}

39
UI/WTextureGLWidget.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef WTEXTUREGLWIDGET_H
#define WTEXTUREGLWIDGET_H
#include <gl/glew.h>
#include <QOpenGLWidget>
#include <Common/CTransform4f.h>
#include <Common/CVector2f.h>
#include <Core/CToken.h>
#include <Resource/CTexture.h>
#include <QTimer>
class WTextureGLWidget : public QOpenGLWidget
{
Q_OBJECT
float mAspectRatio;
CTexture *mpTexture;
CToken mTexToken;
float mTexAspectRatio;
CTransform4f mTexTransform;
CVector2f mCheckerCoords[4];
u32 mContextID;
bool mInitialized;
public:
explicit WTextureGLWidget(QWidget *parent = 0, CTexture *pTex = 0);
~WTextureGLWidget();
void initializeGL();
void paintGL();
void resizeGL(int w, int h);
void SetTexture(CTexture *pTex);
private:
void CalcTexTransform();
void CalcCheckerCoords();
};
#endif // WTEXTUREGLWIDGET_H

View File

@@ -0,0 +1,63 @@
#include "WTexturePreviewPanel.h"
#include "ui_WTexturePreviewPanel.h"
#include "WTextureGLWidget.h"
WTexturePreviewPanel::WTexturePreviewPanel(QWidget *parent, CTexture *pTexture) :
IPreviewPanel(parent),
ui(new Ui::WTexturePreviewPanel)
{
ui->setupUi(this);
SetResource(pTexture);
}
WTexturePreviewPanel::~WTexturePreviewPanel()
{
delete ui;
}
EResType WTexturePreviewPanel::ResType()
{
return eTexture;
}
void WTexturePreviewPanel::SetResource(CResource *pRes)
{
CTexture *pTexture = (CTexture*) pRes;
ui->TextureGLWidget->SetTexture(pTexture);
if (pTexture)
{
std::string Name = StringUtil::GetFileNameWithExtension(pTexture->Source());
ui->TextureNameLabel->setText( QString::fromStdString(Name) );
QString TexInfo;
TexInfo += QString::number(pTexture->Width()) + "x" + QString::number(pTexture->Height());
TexInfo += " ";
switch (pTexture->SourceTexelFormat())
{
case eGX_I4: TexInfo += "I4"; break;
case eGX_I8: TexInfo += "I8"; break;
case eGX_IA4: TexInfo += "IA4"; break;
case eGX_IA8: TexInfo += "IA8"; break;
case eGX_C4: TexInfo += "C4"; break;
case eGX_C8: TexInfo += "C8"; break;
case eGX_C14x2: TexInfo += "C14x2"; break;
case eGX_RGB565: TexInfo += "RGB565"; break;
case eGX_RGB5A3: TexInfo += "RGB5A3"; break;
case eGX_RGBA8: TexInfo += "RGBA8"; break;
case eGX_CMPR: TexInfo += "CMPR"; break;
default: TexInfo += "Invalid Format"; break;
}
TexInfo += " / ";
TexInfo += QString::number(pTexture->NumMipMaps()) + " mipmaps";
ui->TextureInfoLabel->setText(TexInfo);
}
else
{
ui->TextureNameLabel->setText("No texture");
ui->TextureInfoLabel->setText("");
}
}

25
UI/WTexturePreviewPanel.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef WTEXTUREPREVIEWPANEL_H
#define WTEXTUREPREVIEWPANEL_H
#include "IPreviewPanel.h"
#include <Resource/CTexture.h>
namespace Ui {
class WTexturePreviewPanel;
}
class WTexturePreviewPanel : public IPreviewPanel
{
Q_OBJECT
public:
explicit WTexturePreviewPanel(QWidget *parent = 0, CTexture *pTexture = 0);
~WTexturePreviewPanel();
EResType ResType();
void SetResource(CResource *pRes);
private:
Ui::WTexturePreviewPanel *ui;
};
#endif // WTEXTUREPREVIEWPANEL_H

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WTexturePreviewPanel</class>
<widget class="QWidget" name="WTexturePreviewPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>260</width>
<height>305</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<item>
<widget class="WTextureGLWidget" name="TextureGLWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>256</width>
<height>256</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="TextureNameLabel">
<property name="text">
<string>TextureName</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="TextureInfoLabel">
<property name="text">
<string>TextureInfo</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>WTextureGLWidget</class>
<extends>QWidget</extends>
<header>WTextureGLWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

117
UI/WVectorEditor.cpp Normal file
View File

@@ -0,0 +1,117 @@
#include "WVectorEditor.h"
WVectorEditor::WVectorEditor(QWidget *pParent) : QWidget(pParent)
{
mValue = CVector3f::skZero;
mpSpinBoxX = new WDraggableSpinBox(this);
mpSpinBoxY = new WDraggableSpinBox(this);
mpSpinBoxZ = new WDraggableSpinBox(this);
connect(mpSpinBoxX, SIGNAL(valueChanged(double)), this, SLOT(SetX(double)));
connect(mpSpinBoxY, SIGNAL(valueChanged(double)), this, SLOT(SetY(double)));
connect(mpSpinBoxZ, SIGNAL(valueChanged(double)), this, SLOT(SetZ(double)));
/*mpLayout = new QHBoxLayout(this);
mpLayout->setContentsMargins(0,0,0,0);
mpLayout->addWidget(mpSpinBoxX);
mpLayout->addWidget(mpSpinBoxY);
mpLayout->addWidget(mpSpinBoxZ);
setLayout(mpLayout);*/
mpGroupBox = new QGroupBox(this);
mpFormLayout = new QFormLayout(mpGroupBox);
mpFormLayout->addRow(new QLabel("X", mpGroupBox), mpSpinBoxX);
mpFormLayout->addRow(new QLabel("Y", mpGroupBox), mpSpinBoxY);
mpFormLayout->addRow(new QLabel("Z", mpGroupBox), mpSpinBoxZ);
mpGroupBox->setLayout(mpFormLayout);
mpLayout = new QHBoxLayout(this);
mpLayout->addWidget(mpGroupBox);
setLayout(mpLayout);
}
WVectorEditor::WVectorEditor(const CVector3f& Value, QWidget *pParent) : QWidget(pParent)
{
mValue = Value;
mpSpinBoxX = new WDraggableSpinBox(this);
mpSpinBoxY = new WDraggableSpinBox(this);
mpSpinBoxZ = new WDraggableSpinBox(this);
mpSpinBoxX->setValue((double) Value.x);
mpSpinBoxY->setValue((double) Value.y);
mpSpinBoxZ->setValue((double) Value.z);
mpSpinBoxX->setMinimumHeight(21);
mpSpinBoxY->setMinimumHeight(21);
mpSpinBoxZ->setMinimumHeight(21);
mpSpinBoxX->setMaximumHeight(21);
mpSpinBoxY->setMaximumHeight(21);
mpSpinBoxZ->setMaximumHeight(21);
connect(mpSpinBoxX, SIGNAL(valueChanged(double)), this, SLOT(SetX(double)));
connect(mpSpinBoxY, SIGNAL(valueChanged(double)), this, SLOT(SetY(double)));
connect(mpSpinBoxZ, SIGNAL(valueChanged(double)), this, SLOT(SetZ(double)));
mpLayout = new QHBoxLayout(this);
mpLayout->setContentsMargins(0,0,0,0);
mpLayout->addWidget(mpSpinBoxX);
mpLayout->addWidget(mpSpinBoxY);
mpLayout->addWidget(mpSpinBoxZ);
setLayout(mpLayout);
}
WVectorEditor::~WVectorEditor()
{
}
CVector3f WVectorEditor::Value()
{
return mValue;
}
void WVectorEditor::SetValue(const CVector3f& Value)
{
mValue = Value;
mpSpinBoxX->blockSignals(true);
mpSpinBoxY->blockSignals(true);
mpSpinBoxZ->blockSignals(true);
mpSpinBoxX->setValue((double) Value.x);
mpSpinBoxY->setValue((double) Value.y);
mpSpinBoxZ->setValue((double) Value.z);
mpSpinBoxX->blockSignals(false);
mpSpinBoxY->blockSignals(false);
mpSpinBoxZ->blockSignals(false);
}
void WVectorEditor::SetText(const QString &Text)
{
mpGroupBox->setTitle(Text);
}
// ************ SLOTS ************
void WVectorEditor::SetX(double x)
{
mValue.x = (float) x;
mpSpinBoxX->blockSignals(true);
mpSpinBoxX->setValue((double) x);
mpSpinBoxX->blockSignals(false);
}
void WVectorEditor::SetY(double y)
{
mValue.y = (float) y;
mpSpinBoxY->blockSignals(true);
mpSpinBoxY->setValue((double) y);
mpSpinBoxY->blockSignals(false);
}
void WVectorEditor::SetZ(double z)
{
mValue.z = (float) z;
mpSpinBoxZ->blockSignals(true);
mpSpinBoxZ->setValue((double) z);
mpSpinBoxZ->blockSignals(false);
}

43
UI/WVectorEditor.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef WVECTOREDITOR_H
#define WVECTOREDITOR_H
#include <QWidget>
#include <QHBoxLayout>
#include "WDraggableSpinBox.h"
#include <Common/CVector3f.h>
#include <QGroupBox>
#include <QLabel>
#include <QFormLayout>
class WVectorEditor : public QWidget
{
Q_OBJECT
CVector3f mValue;
WDraggableSpinBox *mpSpinBoxX;
WDraggableSpinBox *mpSpinBoxY;
WDraggableSpinBox *mpSpinBoxZ;
QHBoxLayout *mpLayout;
// new layout test
QGroupBox *mpGroupBox;
QLabel *mpLabelX;
QLabel *mpLabelY;
QLabel *mpLabelZ;
QFormLayout *mpFormLayout;
public:
explicit WVectorEditor(QWidget *pParent = 0);
WVectorEditor(const CVector3f& Value, QWidget *pParent = 0);
~WVectorEditor();
CVector3f Value();
void SetValue(const CVector3f& Value);
void SetText(const QString& Text);
public slots:
void SetX(double x);
void SetY(double y);
void SetZ(double z);
};
#endif // WVECTOREDITOR_H

View File

@@ -0,0 +1,54 @@
#include "CLayerEditor.h"
#include "ui_CLayerEditor.h"
CLayerEditor::CLayerEditor(QWidget *parent) :
QDialog(parent),
ui(new Ui::CLayerEditor)
{
ui->setupUi(this);
mpArea = nullptr;
mpModel = new CLayerModel(this);
ui->LayerSelectComboBox->setModel(mpModel);
connect(ui->LayerSelectComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(SetCurrentIndex(int)));
connect(ui->NameLineEdit, SIGNAL(textEdited(QString)), this, SLOT(EditLayerName(QString)));
connect(ui->ActiveCheckBox, SIGNAL(toggled(bool)), this, SLOT(EditLayerActive(bool)));
}
CLayerEditor::~CLayerEditor()
{
delete ui;
}
void CLayerEditor::SetArea(CGameArea *pArea)
{
mpArea = pArea;
mpModel->SetArea(pArea);
SetCurrentIndex(0);
}
// ************ SLOTS ************
void CLayerEditor::SetCurrentIndex(int index)
{
ui->LayerSelectComboBox->blockSignals(true);
ui->LayerSelectComboBox->setCurrentIndex(index);
ui->LayerSelectComboBox->blockSignals(false);
QModelIndex ModelIndex = mpModel->index(index);
mpCurrentLayer = mpModel->Layer(ModelIndex);
ui->NameLineEdit->setText(QString::fromStdString(mpCurrentLayer->Name()));
ui->ActiveCheckBox->setChecked(mpCurrentLayer->IsActive());
}
void CLayerEditor::EditLayerName(const QString &name)
{
mpCurrentLayer->SetName(name.toStdString());
ui->LayerSelectComboBox->update();
}
void CLayerEditor::EditLayerActive(bool active)
{
mpCurrentLayer->SetActive(active);
}

View File

@@ -0,0 +1,32 @@
#ifndef CLAYEREDITOR_H
#define CLAYEREDITOR_H
#include <QDialog>
#include "CLayerModel.h"
namespace Ui {
class CLayerEditor;
}
class CLayerEditor : public QDialog
{
Q_OBJECT
CGameArea *mpArea;
CLayerModel *mpModel;
CScriptLayer *mpCurrentLayer;
public:
explicit CLayerEditor(QWidget *parent = 0);
~CLayerEditor();
void SetArea(CGameArea *pArea);
public slots:
void SetCurrentIndex(int index);
void EditLayerName(const QString& name);
void EditLayerActive(bool active);
private:
Ui::CLayerEditor *ui;
};
#endif // CLAYEREDITOR_H

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CLayerEditor</class>
<widget class="QDialog" name="CLayerEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>68</height>
</rect>
</property>
<property name="windowTitle">
<string>Edit Layers</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QComboBox" name="LayerSelectComboBox"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="NameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="NameLineEdit"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="ActiveLabel">
<property name="text">
<string>Active:</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="ActiveCheckBox">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,46 @@
#include "CLayerModel.h"
CLayerModel::CLayerModel(QObject *pParent) : QAbstractListModel(pParent)
{
mpArea = nullptr;
mHasGenerateLayer = false;
}
CLayerModel::~CLayerModel()
{
}
int CLayerModel::rowCount(const QModelIndex &parent) const
{
if (!mpArea) return 0;
if (mHasGenerateLayer) return mpArea->GetScriptLayerCount() + 1;
else return mpArea->GetScriptLayerCount();
}
QVariant CLayerModel::data(const QModelIndex &index, int role) const
{
if (mpArea && (role == Qt::DisplayRole) && (index.row() < rowCount(QModelIndex())))
return QString::fromStdString(Layer(index)->Name());
return QVariant::Invalid;
}
void CLayerModel::SetArea(CGameArea *pArea)
{
mpArea = pArea;
mHasGenerateLayer = (pArea->GetGeneratorLayer() != nullptr);
emit layoutChanged();
}
CScriptLayer* CLayerModel::Layer(const QModelIndex& index) const
{
if (!mpArea) return nullptr;
u32 NumLayers = mpArea->GetScriptLayerCount();
if (index.row() < NumLayers)
return mpArea->GetScriptLayer(index.row());
if (mHasGenerateLayer && (index.row() == NumLayers))
return mpArea->GetGeneratorLayer();
return nullptr;
}

View File

@@ -0,0 +1,21 @@
#ifndef CLAYERMODEL_H
#define CLAYERMODEL_H
#include <QAbstractListModel>
#include <Resource/CGameArea.h>
class CLayerModel : public QAbstractListModel
{
CGameArea *mpArea;
bool mHasGenerateLayer;
public:
explicit CLayerModel(QObject *pParent = 0);
~CLayerModel();
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
void SetArea(CGameArea *pArea);
CScriptLayer* Layer(const QModelIndex& index) const;
};
#endif // CLAYERMODEL_H

View File

@@ -0,0 +1,119 @@
#include "CLayersInstanceModel.h"
/* The tree has 3 levels:
* 1. Node Type (Script Object, Light) - represented with ID of 0
* 2. Layer - represented with flags
* 3. Instance - represented with pointer to instance (0x1 bit is guaranteed to be clear)
*
* Flags for Layer tree items:
* AAAAAAAAAAAAAAAAAAAAAAAAAAABBBBC
* A: Row index
* B: Node type row index
* C: Item type (ObjType, Instance)
*/
#define LAYERS_ROW_INDEX_MASK 0xFFFFFFE0
#define LAYERS_NODE_TYPE_MASK 0x0000001E
#define LAYERS_ITEM_TYPE_MASK 0x00000001
#define LAYERS_ROW_INDEX_SHIFT 5
#define LAYERS_NODE_TYPE_SHIFT 1
#define LAYERS_ITEM_TYPE_SHIFT 0
CLayersInstanceModel::CLayersInstanceModel(QObject *pParent) : QAbstractItemModel(pParent)
{
}
CLayersInstanceModel::~CLayersInstanceModel()
{
}
QVariant CLayersInstanceModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole))
{
switch (section)
{
case 0: return "Name";
case 1: return "Type";
case 2: return "Show";
}
}
return QVariant::Invalid;
}
QModelIndex CLayersInstanceModel::index(int row, int column, const QModelIndex &parent) const
{
return QModelIndex();
}
QModelIndex CLayersInstanceModel::parent(const QModelIndex &child) const
{
return QModelIndex();
}
int CLayersInstanceModel::rowCount(const QModelIndex &parent) const
{
return 0;
}
int CLayersInstanceModel::columnCount(const QModelIndex &parent) const
{
return 3;
}
QVariant CLayersInstanceModel::data(const QModelIndex &index, int role) const
{
return QVariant::Invalid;
}
void CLayersInstanceModel::SetEditor(CWorldEditor *pEditor)
{
mpEditor = pEditor;
mpScene = (pEditor ? pEditor->Scene() : nullptr);
mpArea = (pEditor ? pEditor->ActiveArea() : nullptr);
}
void CLayersInstanceModel::NodeCreated(CSceneNode *pNode)
{
emit layoutChanged();
}
void CLayersInstanceModel::NodeDeleted(CSceneNode *pNode)
{
emit layoutChanged();
}
CScriptLayer* CLayersInstanceModel::IndexLayer(const QModelIndex& index) const
{
return nullptr;
}
CScriptObject* CLayersInstanceModel::IndexObject(const QModelIndex& index) const
{
return nullptr;
}
// ************ STATIC ************
CLayersInstanceModel::EIndexType CLayersInstanceModel::IndexType(const QModelIndex& index)
{
if (!index.isValid()) return eRootIndex;
else if (index.internalId() == 0) return eNodeTypeIndex;
else if (((index.internalId() & LAYERS_ITEM_TYPE_MASK) >> LAYERS_ITEM_TYPE_SHIFT) == 1) return eLayerIndex;
else return eInstanceIndex;
}
CLayersInstanceModel::ENodeType CLayersInstanceModel::IndexNodeType(const QModelIndex& index)
{
EIndexType type = IndexType(index);
switch (type)
{
case eRootIndex: return eInvalidType;
case eNodeTypeIndex: return (ENodeType) index.row();
case eLayerIndex: return (ENodeType) index.parent().row();
case eInstanceIndex: return (ENodeType) index.parent().parent().row();
default: return eInvalidType;
}
}

View File

@@ -0,0 +1,49 @@
#ifndef CLAYERSINSTANCEMODEL_H
#define CLAYERSINSTANCEMODEL_H
#include <QAbstractItemModel>
#include <Resource/script/CScriptLayer.h>
#include "../CWorldEditor.h"
// Only supports script layers atm - maybe light layers later...?
class CLayersInstanceModel : public QAbstractItemModel
{
Q_OBJECT
public:
enum EIndexType {
eRootIndex, eNodeTypeIndex, eLayerIndex, eInstanceIndex
};
enum ENodeType {
eScriptType = 0x0,
eLightType = 0x1,
eInvalidType = 0xFF
};
private:
CWorldEditor *mpEditor;
CSceneManager *mpScene;
CGameArea *mpArea;
public:
explicit CLayersInstanceModel(QObject *pParent = 0);
~CLayersInstanceModel();
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QModelIndex index(int row, int column, const QModelIndex &parent) const;
QModelIndex parent(const QModelIndex &child) const;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
void SetEditor(CWorldEditor *pEditor);
void NodeCreated(CSceneNode *pNode);
void NodeDeleted(CSceneNode *pNode);
CScriptLayer* IndexLayer(const QModelIndex& index) const;
CScriptObject* IndexObject(const QModelIndex& index) const;
// Static
static EIndexType IndexType(const QModelIndex& index);
static ENodeType IndexNodeType(const QModelIndex& index);
};
#endif // CLAYERSINSTANCEMODEL_H

View File

@@ -0,0 +1,101 @@
#include "CLinkModel.h"
#include <Resource/CGameArea.h>
#include <Resource/script/CMasterTemplate.h>
CLinkModel::CLinkModel(QObject *pParent) : QAbstractTableModel(pParent)
{
mpObject = nullptr;
mType = eOutgoing;
}
void CLinkModel::SetObject(CScriptObject *pObj)
{
mpObject = pObj;
emit layoutChanged();
}
void CLinkModel::SetConnectionType(EConnectionType type)
{
mType = type;
emit layoutChanged();
}
int CLinkModel::rowCount(const QModelIndex&) const
{
if (mpObject)
{
if (mType == eIncoming)
return mpObject->NumInLinks();
else
return mpObject->NumOutLinks();
}
else return 0;
}
int CLinkModel::columnCount(const QModelIndex &parent) const
{
return 3;
}
QVariant CLinkModel::data(const QModelIndex &index, int role) const
{
if (!mpObject) return QVariant::Invalid;
else if ((role == Qt::DisplayRole) || (role == Qt::ToolTipRole))
{
SLink link = (mType == eIncoming ? mpObject->InLink(index.row()) : mpObject->OutLink(index.row()));
switch (index.column())
{
case 0: // Column 0 - Target Object
{
CScriptObject *pTargetObj = mpObject->Area()->GetInstanceByID(link.ObjectID);
if (role == Qt::DisplayRole) {
if (pTargetObj) return QString::fromStdString(pTargetObj->GetInstanceName());
else return QString("0x") + QString::number(link.ObjectID, 16);
}
else {
QString ObjType = QString("[%1] ").arg(QString::fromStdString(pTargetObj->Template()->TemplateName()));
if (pTargetObj) return ObjType + QString::fromStdString(pTargetObj->GetInstanceName());
else return ObjType + QString("0x") + QString::number(link.ObjectID, 16);
}
}
case 1: // Column 1 - State
{
std::string StateName = mpObject->MasterTemplate()->StateByID(link.State);
return QString::fromStdString(StateName);
}
case 2: // Column 2 - Message
{
std::string MessageName = mpObject->MasterTemplate()->MessageByID(link.Message);
return QString::fromStdString(MessageName);
}
default:
return QVariant::Invalid;
}
}
else return QVariant::Invalid;
}
QVariant CLinkModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole))
{
switch (section)
{
case 0: return (mType == eIncoming ? "Sender" : "Target");
case 1: return "State";
case 2: return "Message";
default: return QVariant::Invalid;
}
}
else return QVariant::Invalid;
}

View File

@@ -0,0 +1,30 @@
#ifndef CCONNECTIONMODEL_H
#define CCONNECTIONMODEL_H
#include <QAbstractTableModel>
#include <Resource/script/CScriptObject.h>
class CLinkModel : public QAbstractTableModel
{
Q_OBJECT
public:
enum EConnectionType {
eIncoming, eOutgoing
};
private:
CScriptObject *mpObject;
EConnectionType mType;
public:
explicit CLinkModel(QObject *pParent = 0);
void SetObject(CScriptObject *pObj);
void SetConnectionType(EConnectionType type);
int rowCount(const QModelIndex& parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
};
#endif // CCONNECTIONMODEL_H

View File

@@ -0,0 +1,451 @@
#include "CTypesInstanceModel.h"
#include <Scene/CScriptNode.h>
#include <QApplication>
#include <QIcon>
/* The tree has 3 levels:
* 1. Node Type (Script Object, Light, World Mesh, etc) - represented with ID of 0
* 2. Object Type (Actor, Platform, SpawnPoint, etc) - represented with flags
* 3. Instance - represented with pointer to instance (0x1 bit is guaranteed to be clear)
*
* Flags for Object Type tree items
* AAAAAAAAAAAAAAAAAAAAAAAAAAABBBBC
* A: Row index
* B: Node type row index
* C: Item type (ObjType, Instance)
*/
#define TYPES_ROW_INDEX_MASK 0xFFFFFFE0
#define TYPES_NODE_TYPE_MASK 0x0000001E
#define TYPES_ITEM_TYPE_MASK 0x00000001
#define TYPES_ROW_INDEX_SHIFT 5
#define TYPES_NODE_TYPE_SHIFT 1
#define TYPES_ITEM_TYPE_SHIFT 0
bool SortTemplatesAlphabetical(CScriptTemplate *pA, CScriptTemplate *pB)
{
return (pA->TemplateName() < pB->TemplateName());
}
CTypesInstanceModel::CTypesInstanceModel(QObject *pParent) : QAbstractItemModel(pParent)
{
mpEditor = nullptr;
mpScene = nullptr;
mpArea = nullptr;
mpCurrentMaster = nullptr;
mModelType = eLayers;
mBaseItems << "Script";
}
CTypesInstanceModel::~CTypesInstanceModel()
{
}
QVariant CTypesInstanceModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole))
{
switch (section)
{
case 0: return "Name";
case 1: return (mModelType == eLayers ? "Type" : "Layer");
case 2: return "Show";
}
}
return QVariant::Invalid;
}
QModelIndex CTypesInstanceModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
EIndexType type = IndexType(parent);
// Node type index
if (type == eRootIndex)
{
if (row < mBaseItems.count())
return createIndex(row, column, quint32(0));
else
return QModelIndex();
}
// Object type index
else if (type == eNodeTypeIndex)
return createIndex(row, column, ((row << TYPES_ROW_INDEX_SHIFT) | (parent.row() << TYPES_NODE_TYPE_SHIFT) | 1));
// Instance index
else if (type == eObjectTypeIndex)
{
u32 RootRow = parent.parent().row();
// Object
if (RootRow == 0)
{
if (mModelType == eLayers)
{
CScriptLayer *pLayer = mpArea->GetScriptLayer(parent.row());
if (row >= pLayer->GetNumObjects())
return QModelIndex();
else
return createIndex(row, column, (*pLayer)[row]);
}
else if (mModelType == eTypes)
{
const std::list<CScriptObject*>& list = mTemplateList[parent.row()]->ObjectList();
if (row >= list.size())
return QModelIndex();
else
{
auto it = std::next(list.begin(), row);
return createIndex(row, column, *it);
}
}
}
// todo: implement getters for other types
}
return QModelIndex();
}
QModelIndex CTypesInstanceModel::parent(const QModelIndex &child) const
{
EIndexType type = IndexType(child);
// Root parent
if (type == eNodeTypeIndex)
return QModelIndex();
// Node type parent
if (type == eObjectTypeIndex)
{
u32 NodeTypeRow = (child.internalId() & TYPES_NODE_TYPE_MASK) >> TYPES_NODE_TYPE_SHIFT;
return createIndex(NodeTypeRow, 0, quint32(0));
}
// Object type parent
else if (type == eInstanceIndex)
{
CScriptObject *pObj = static_cast<CScriptObject*> (child.internalPointer());
if (mModelType == eLayers)
{
CScriptLayer *pLayer = pObj->Layer();
for (u32 iLyr = 0; iLyr < mpArea->GetScriptLayerCount(); iLyr++)
{
if (mpArea->GetScriptLayer(iLyr) == pLayer)
return createIndex(iLyr, 0, (iLyr << TYPES_ROW_INDEX_SHIFT) | 1);
}
}
else if (mModelType == eTypes)
{
CScriptTemplate *pTemp = pObj->Template();
for (u32 iTemp = 0; iTemp < mTemplateList.size(); iTemp++)
{
if (mTemplateList[iTemp] == pTemp)
return createIndex(iTemp, 0, (iTemp << TYPES_ROW_INDEX_SHIFT) | 1);
}
}
}
return QModelIndex();
}
int CTypesInstanceModel::rowCount(const QModelIndex &parent) const
{
EIndexType type = IndexType(parent);
// Node types
if (type == eRootIndex)
return mBaseItems.count();
// Object types
else if (type == eNodeTypeIndex)
{
// Script Objects
if (parent.row() == 0) {
if (mModelType == eLayers)
return (mpArea ? mpArea->GetScriptLayerCount() : 0);
else
return mTemplateList.size();
}
else
return 0;
}
// Instances
else if (type == eObjectTypeIndex)
{
u32 RowIndex = ((parent.internalId() & TYPES_ROW_INDEX_MASK) >> TYPES_ROW_INDEX_SHIFT);
if (mModelType == eLayers)
return (mpArea ? mpArea->GetScriptLayer(RowIndex)->GetNumObjects() : 0);
else
return mTemplateList[RowIndex]->NumObjects();
}
else
return 0;
}
int CTypesInstanceModel::columnCount(const QModelIndex &parent) const
{
return 3;
}
QVariant CTypesInstanceModel::data(const QModelIndex &index, int role) const
{
EIndexType type = IndexType(index);
// Name/Layer
if ((role == Qt::DisplayRole) || (role == Qt::ToolTipRole))
{
// Node types
if (type == eNodeTypeIndex)
{
if (index.column() == 0)
return mBaseItems[index.row()];
else
return QVariant::Invalid;
}
// Object types
else if (type == eObjectTypeIndex)
{
if (index.column() == 0) {
if (mModelType == eLayers)
return QString::fromStdString(mpEditor->ActiveArea()->GetScriptLayer(index.row())->Name());
else
return QString::fromStdString(mTemplateList[index.row()]->TemplateName());
}
// todo: show/hide button in column 2
else
return QVariant::Invalid;
}
// Instances
else if (type == eInstanceIndex)
{
// todo: show/hide button
CScriptObject *pObj = static_cast<CScriptObject*>(index.internalPointer());
if (index.column() == 0)
return QString::fromStdString(pObj->GetInstanceName());
else if (index.column() == 1)
{
if (mModelType == eLayers)
return QString::fromStdString(pObj->Template()->TemplateName());
else if (mModelType == eTypes)
return QString::fromStdString(pObj->Layer()->Name());
}
else
return QVariant::Invalid;
}
}
// Show/Hide Buttons
else if ((role == Qt::DecorationRole) && (index.column() == 2))
{
if (!mpScene) return QVariant::Invalid;
static QIcon Visible(":/icons/EditorAssets/Show.png");
static QIcon Invisible(":/icons/EditorAssets/Hide.png");
// Show/Hide Node Types
if (type == eNodeTypeIndex)
{
// Commented out pending a proper implementation of turning node types on/off from the instance view
/*bool IsVisible;
switch (index.row())
{
case 0: IsVisible = mpScene->AreScriptObjectsEnabled();
case 1: IsVisible = mpScene->AreLightsEnabled();
default: IsVisible = false;
}
if (IsVisible) return Visible;
else return Invisible;*/
}
// Show/Hide Object Types
else if (type == eObjectTypeIndex)
{
if (mModelType == eLayers)
{
CScriptLayer *pLayer = IndexLayer(index);
if (pLayer->IsVisible()) return Visible;
else return Invisible;
}
else if (mModelType == eTypes)
{
CScriptTemplate *pTemp = IndexTemplate(index);
if (pTemp->IsVisible()) return Visible;
else return Invisible;
}
}
// Show/Hide Instance
else if (type == eInstanceIndex)
{
CScriptObject *pObj = IndexObject(index);
CScriptNode *pNode = mpScene->NodeForObject(pObj);
if (pNode->MarkedVisible()) return Visible;
else return Invisible;
}
}
return QVariant::Invalid;
}
void CTypesInstanceModel::SetEditor(CWorldEditor *pEditor)
{
mpEditor = pEditor;
mpScene = (pEditor ? pEditor->Scene() : nullptr);
}
void CTypesInstanceModel::SetMaster(CMasterTemplate *pMaster)
{
mpCurrentMaster = pMaster;
GenerateList();
}
void CTypesInstanceModel::SetArea(CGameArea *pArea)
{
beginResetModel();
mpArea = pArea;
endResetModel();
}
void CTypesInstanceModel::SetModelType(EInstanceModelType type)
{
mModelType = type;
}
void CTypesInstanceModel::NodeCreated(CSceneNode *pNode)
{
if (mModelType == eTypes)
{
if (pNode->NodeType() == eScriptNode)
{
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
CScriptObject *pObj = pScript->Object();
pObj->Template()->SortObjects();
if (pObj->Template()->NumObjects() == 1)
{
mTemplateList << pObj->Template();
qSort(mTemplateList.begin(), mTemplateList.end(), SortTemplatesAlphabetical);
emit layoutChanged();
}
}
}
}
void CTypesInstanceModel::NodeDeleted(CSceneNode *pNode)
{
if (mModelType = eTypes)
{
if (pNode->NodeType() == eScriptNode)
{
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
CScriptObject *pObj = pScript->Object();
if (pObj->Template()->NumObjects() == 0)
{
for (auto it = mTemplateList.begin(); it != mTemplateList.end(); it++)
{
if (*it == pObj->Template())
{
mTemplateList.erase(it);
break;
}
}
emit layoutChanged();
}
}
}
}
CScriptLayer* CTypesInstanceModel::IndexLayer(const QModelIndex& index) const
{
if ((mModelType != eLayers) || (IndexNodeType(index) != eScriptType) || (IndexType(index) != eObjectTypeIndex))
return nullptr;
u32 RowIndex = ((index.internalId() & TYPES_ROW_INDEX_MASK) >> TYPES_ROW_INDEX_SHIFT);
return mpArea->GetScriptLayer(RowIndex);
}
CScriptTemplate* CTypesInstanceModel::IndexTemplate(const QModelIndex& index) const
{
if ((mModelType != eTypes) || (IndexNodeType(index) != eScriptType) || (IndexType(index) != eObjectTypeIndex))
return nullptr;
u32 RowIndex = ((index.internalId() & TYPES_ROW_INDEX_MASK) >> TYPES_ROW_INDEX_SHIFT);
return mTemplateList[RowIndex];
}
CScriptObject* CTypesInstanceModel::IndexObject(const QModelIndex& index) const
{
if ((IndexNodeType(index) != eScriptType) || (IndexType(index) != eInstanceIndex))
return nullptr;
return static_cast<CScriptObject*>(index.internalPointer());
}
// ************ STATIC ************
CTypesInstanceModel::EIndexType CTypesInstanceModel::IndexType(const QModelIndex& index)
{
if (!index.isValid()) return eRootIndex;
else if (index.internalId() == 0) return eNodeTypeIndex;
else if (((index.internalId() & TYPES_ITEM_TYPE_MASK) >> TYPES_ITEM_TYPE_SHIFT) == 1) return eObjectTypeIndex;
else return eInstanceIndex;
}
CTypesInstanceModel::ENodeType CTypesInstanceModel::IndexNodeType(const QModelIndex& index)
{
EIndexType type = IndexType(index);
switch (type)
{
case eRootIndex: return eInvalidType;
case eNodeTypeIndex: return (ENodeType) index.row();
case eObjectTypeIndex: return (ENodeType) index.parent().row();
case eInstanceIndex: return (ENodeType) index.parent().parent().row();
default: return eInvalidType;
}
}
// ************ PRIVATE ************
void CTypesInstanceModel::GenerateList()
{
beginResetModel();
mTemplateList.clear();
if (mpCurrentMaster)
{
u32 NumTemplates = mpCurrentMaster->NumScriptTemplates();
for (u32 iTemp = 0; iTemp < NumTemplates; iTemp++)
{
CScriptTemplate *pTemp = mpCurrentMaster->TemplateByIndex(iTemp);
if (pTemp->NumObjects() > 0)
mTemplateList << pTemp;
}
qSort(mTemplateList.begin(), mTemplateList.end(), SortTemplatesAlphabetical);
}
endResetModel();
}

View File

@@ -0,0 +1,67 @@
#ifndef CTYPESINSTANCEMODEL_H
#define CTYPESINSTANCEMODEL_H
#include <QAbstractItemModel>
#include <QList>
#include <Resource/script/CMasterTemplate.h>
#include <Resource/script/CScriptTemplate.h>
#include <Scene/CSceneNode.h>
#include "../CWorldEditor.h"
class CTypesInstanceModel : public QAbstractItemModel
{
Q_OBJECT
public:
enum EIndexType {
eRootIndex, eNodeTypeIndex, eObjectTypeIndex, eInstanceIndex
};
enum ENodeType {
eScriptType = 0x0,
eLightType = 0x1,
eInvalidType = 0xFF
};
enum EInstanceModelType {
eLayers, eTypes
};
private:
CWorldEditor *mpEditor;
CSceneManager *mpScene;
CGameArea *mpArea;
CMasterTemplate *mpCurrentMaster;
EInstanceModelType mModelType;
QList<CScriptTemplate*> mTemplateList;
QStringList mBaseItems;
public:
explicit CTypesInstanceModel(QObject *pParent = 0);
~CTypesInstanceModel();
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
void SetEditor(CWorldEditor *pEditor);
void SetMaster(CMasterTemplate *pMaster);
void SetArea(CGameArea *pArea);
void SetModelType(EInstanceModelType type);
void NodeCreated(CSceneNode *pNode);
void NodeDeleted(CSceneNode *pNode);
CScriptLayer* IndexLayer(const QModelIndex& index) const;
CScriptTemplate* IndexTemplate(const QModelIndex& index) const;
CScriptObject* IndexObject(const QModelIndex& index) const;
// Static
static EIndexType IndexType(const QModelIndex& index);
static ENodeType IndexNodeType(const QModelIndex& index);
private:
void GenerateList();
};
#endif // CTYPESINSTANCEMODEL_H

View File

@@ -0,0 +1,14 @@
#include "WCreateTab.h"
#include "ui_WCreateTab.h"
WCreateTab::WCreateTab(QWidget *parent) :
QWidget(parent),
ui(new Ui::WCreateTab)
{
ui->setupUi(this);
}
WCreateTab::~WCreateTab()
{
delete ui;
}

View File

@@ -0,0 +1,22 @@
#ifndef WCREATETAB_H
#define WCREATETAB_H
#include <QWidget>
namespace Ui {
class WCreateTab;
}
class WCreateTab : public QWidget
{
Q_OBJECT
public:
explicit WCreateTab(QWidget *parent = 0);
~WCreateTab();
private:
Ui::WCreateTab *ui;
};
#endif // WCREATETAB_H

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WCreateTab</class>
<widget class="QWidget" name="WCreateTab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>216</width>
<height>421</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,163 @@
#include "WInstancesTab.h"
#include "ui_WInstancesTab.h"
#include "../CWorldEditor.h"
#include <Core/CSceneManager.h>
WInstancesTab::WInstancesTab(QWidget *parent) :
QWidget(parent),
ui(new Ui::WInstancesTab)
{
ui->setupUi(this);
mpEditor = nullptr;
mpLayersModel = new CTypesInstanceModel(this);
mpLayersModel->SetModelType(CTypesInstanceModel::eLayers);
mpTypesModel = new CTypesInstanceModel(this);
mpTypesModel->SetModelType(CTypesInstanceModel::eTypes);
ui->LayersTreeView->setModel(mpLayersModel);
ui->LayersTreeView->header()->setSectionResizeMode(2, QHeaderView::Fixed);
ui->LayersTreeView->resizeColumnToContents(2);
ui->TypesTreeView->setModel(mpTypesModel);
ui->TypesTreeView->header()->setSectionResizeMode(2, QHeaderView::Fixed);
ui->TypesTreeView->resizeColumnToContents(2);
// Create context menu
mpTreeContextMenu = new QMenu(this);
mpHideInstance = new QAction("Hide instance", this);
mpHideType = new QAction("", this);
mpHideAllExceptType = new QAction("", this);
mpTreeContextMenu->addAction(mpHideInstance);
mpTreeContextMenu->addAction(mpHideType);
mpTreeContextMenu->addAction(mpHideAllExceptType);
// Configure signals/slots
connect(ui->LayersTreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(OnTreeClick(QModelIndex)));
connect(ui->LayersTreeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnTreeDoubleClick(QModelIndex)));
connect(ui->TypesTreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(OnTreeClick(QModelIndex)));
connect(ui->TypesTreeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnTreeDoubleClick(QModelIndex)));
connect(mpHideInstance, SIGNAL(triggered()), this, SLOT(OnHideInstanceAction()));
connect(mpHideType, SIGNAL(triggered()), this, SLOT(OnHideTypeAction()));
connect(mpHideAllExceptType, SIGNAL(triggered()), this, SLOT(OnHideAllExceptTypeAction()));
}
WInstancesTab::~WInstancesTab()
{
delete ui;
}
void WInstancesTab::SetEditor(CWorldEditor *pEditor, CSceneManager *pScene)
{
mpEditor = pEditor;
mpScene = pScene;
mpTypesModel->SetEditor(pEditor);
mpLayersModel->SetEditor(pEditor);
}
void WInstancesTab::SetMaster(CMasterTemplate *pMaster)
{
mpTypesModel->SetMaster(pMaster);
ExpandTopLevelItems();
}
void WInstancesTab::SetArea(CGameArea *pArea)
{
mpLayersModel->SetArea(pArea);
ExpandTopLevelItems();
}
// ************ PRIVATE SLOTS ************
void WInstancesTab::OnTreeClick(QModelIndex Index)
{
// Single click is used to process show/hide events
if (Index.column() == 2)
{
// Show/Hide Instance
if (mpTypesModel->IndexType(Index) == CTypesInstanceModel::eInstanceIndex)
{
CScriptObject *pObj = mpTypesModel->IndexObject(Index);
CScriptNode *pNode = mpScene->NodeForObject(pObj);
pNode->SetVisible(!pNode->IsVisible());
}
// Show/Hide Object Type
else if (mpTypesModel->IndexType(Index) == CTypesInstanceModel::eObjectTypeIndex)
{
if (sender() == ui->LayersTreeView)
{
CScriptLayer *pLayer = mpLayersModel->IndexLayer(Index);
pLayer->SetVisible(!pLayer->IsVisible());
}
else if (sender() == ui->TypesTreeView)
{
CScriptTemplate *pTmp = mpTypesModel->IndexTemplate(Index);
pTmp->SetVisible(!pTmp->IsVisible());
}
}
// Show/Hide Node Type
else if (mpTypesModel->IndexType(Index) == CTypesInstanceModel::eNodeTypeIndex)
{
CTypesInstanceModel::ENodeType type = mpTypesModel->IndexNodeType(Index);
if (type == CTypesInstanceModel::eScriptType)
mpScene->SetObjects(!mpScene->AreScriptObjectsEnabled());
}
if (sender() == ui->LayersTreeView)
ui->LayersTreeView->update(Index);
else if (sender() == ui->TypesTreeView)
ui->TypesTreeView->update(Index);
}
}
void WInstancesTab::OnTreeDoubleClick(QModelIndex Index)
{
CTypesInstanceModel::EIndexType IndexType = mpTypesModel->IndexType(Index);
if ((mpEditor) && (IndexType == CTypesInstanceModel::eInstanceIndex))
{
CTypesInstanceModel::ENodeType NodeType = mpTypesModel->IndexNodeType(Index);
CSceneNode *pSelectedNode = nullptr;
if (NodeType == CTypesInstanceModel::eScriptType)
pSelectedNode = mpScene->NodeForObject( static_cast<CScriptObject*>(Index.internalPointer()) );
if (pSelectedNode)
{
mpEditor->ClearSelection();
mpEditor->SelectNode(pSelectedNode);
}
}
}
void WInstancesTab::OnHideInstanceAction()
{
}
void WInstancesTab::OnHideTypeAction()
{
}
void WInstancesTab::OnHideAllExceptTypeAction()
{
}
// ************ PRIVATE ************
void WInstancesTab::ExpandTopLevelItems()
{
for (u32 iModel = 0; iModel < 2; iModel++)
{
QAbstractItemModel *pModel = (iModel == 0 ? mpLayersModel : mpTypesModel);
QTreeView *pView = (iModel == 0 ? ui->LayersTreeView : ui->TypesTreeView);
QModelIndex Index = pModel->index(0,0);
while (Index.isValid())
{
pView->expand(Index);
Index = Index.sibling(Index.row() + 1, 0);
}
}
}

View File

@@ -0,0 +1,51 @@
#ifndef WINSTANCESTAB_H
#define WINSTANCESTAB_H
#include <QWidget>
#include <QAction>
#include <QMenu>
#include "CTypesInstanceModel.h"
class CWorldEditor;
class CSceneManager;
namespace Ui {
class WInstancesTab;
}
class WInstancesTab : public QWidget
{
Q_OBJECT
CWorldEditor *mpEditor;
CSceneManager *mpScene;
CTypesInstanceModel *mpLayersModel;
CTypesInstanceModel *mpTypesModel;
// Tree right-click context menu
QMenu *mpTreeContextMenu;
QAction *mpHideInstance;
QAction *mpHideType;
QAction *mpHideAllExceptType;
public:
explicit WInstancesTab(QWidget *parent = 0);
~WInstancesTab();
void SetEditor(CWorldEditor *pEditor, CSceneManager *pScene);
void SetMaster(CMasterTemplate *pMaster);
void SetArea(CGameArea *pArea);
private slots:
void OnTreeClick(QModelIndex Index);
void OnTreeDoubleClick(QModelIndex Index);
void OnHideInstanceAction();
void OnHideTypeAction();
void OnHideAllExceptTypeAction();
private:
Ui::WInstancesTab *ui;
void ExpandTopLevelItems();
};
#endif // WINSTANCESTAB_H

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WInstancesTab</class>
<widget class="QWidget" name="WInstancesTab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>253</width>
<height>437</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item>
<widget class="QTabWidget" name="TabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="ShowLayersTab">
<attribute name="title">
<string>Layer</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeView" name="LayersTreeView">
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="indentation">
<number>13</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="ShowTypesTab">
<attribute name="title">
<string>Type</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTreeView" name="TypesTreeView">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="indentation">
<number>13</number>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,145 @@
#include "WModifyTab.h"
#include "ui_WModifyTab.h"
#include <Scene/CScriptNode.h>
#include <QScrollArea>
#include <QScrollBar>
#include "../CWorldEditor.h"
WModifyTab::WModifyTab(QWidget *pParent) :
QWidget(pParent),
ui(new Ui::WModifyTab)
{
ui->setupUi(this);
mpCurPropEditor = nullptr;
mpInLinkModel = new CLinkModel(this);
mpInLinkModel->SetConnectionType(CLinkModel::eIncoming);
mpOutLinkModel = new CLinkModel(this);
mpOutLinkModel->SetConnectionType(CLinkModel::eOutgoing);
ui->InLinksTableView->setModel(mpInLinkModel);
ui->OutLinksTableView->setModel(mpOutLinkModel);
ui->InLinksTableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
ui->OutLinksTableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
connect(ui->InLinksTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnLinkTableDoubleClick(QModelIndex)));
connect(ui->OutLinksTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnLinkTableDoubleClick(QModelIndex)));
ClearUI();
}
WModifyTab::~WModifyTab()
{
delete ui;
}
void WModifyTab::SetEditor(CWorldEditor *pEditor)
{
mpWorldEditor = pEditor;
}
void WModifyTab::GenerateUI(std::list<CSceneNode*>& Selection)
{
WPropertyEditor *pOldEditor = mpCurPropEditor;
ClearUI();
if (Selection.size() == 1)
{
mpSelectedNode = Selection.front();
// todo: set up editing UI for Light Nodes
if (mpSelectedNode->NodeType() == eScriptNode)
{
ui->ObjectsTabWidget->show();
CScriptNode *pScriptNode = static_cast<CScriptNode*>(mpSelectedNode);
CScriptObject *pObj = pScriptNode->Object();
CScriptTemplate *pTemplate = pObj->Template();
CPropertyStruct *pProperties = pObj->Properties();
// Check whether a cached UI for this object exists
auto it = mCachedPropEditors.find(pTemplate);
// Load precached UI
if (it != mCachedPropEditors.end())
{
mpCurPropEditor = *it;
mpCurPropEditor->SetProperty(pProperties);
}
// Generate new UI
else
{
mpCurPropEditor = new WPropertyEditor(ui->PropertiesScrollContents, pProperties);
mCachedPropEditors[pTemplate] = mpCurPropEditor;
}
ui->PropertiesScrollLayout->insertWidget(0, mpCurPropEditor);
mpCurPropEditor->show();
// Scroll back up to the top, but only if this is a new editor.
// (This is so clicking on multiple objects of the same type, or even
// the same object twice, won't cause you to lose your place.)
if (pOldEditor != mpCurPropEditor)
{
ui->PropertiesScrollArea->horizontalScrollBar()->setValue(0);
ui->PropertiesScrollArea->verticalScrollBar()->setValue(0);
}
// Set up connection table model
mpInLinkModel->SetObject(pObj);
mpOutLinkModel->SetObject(pObj);
}
}
else
ClearUI();
}
void WModifyTab::ClearUI()
{
if (mpCurPropEditor)
{
ui->PropertiesScrollLayout->removeWidget(mpCurPropEditor);
mpCurPropEditor->hide();
mpCurPropEditor = nullptr;
}
ui->ObjectsTabWidget->hide();
ui->LightGroupBox->hide();
}
void WModifyTab::ClearCachedEditors()
{
foreach(WPropertyEditor *pEditor, mCachedPropEditors)
delete pEditor;
mCachedPropEditors.clear();
}
void WModifyTab::OnLinkTableDoubleClick(QModelIndex Index)
{
if (Index.column() == 0)
{
// The link table will only be visible if the selected node is a script node
CScriptNode *pNode = static_cast<CScriptNode*>(mpSelectedNode);
SLink Link;
if (sender() == ui->InLinksTableView)
Link = pNode->Object()->InLink(Index.row());
else if (sender() == ui->OutLinksTableView)
Link = pNode->Object()->OutLink(Index.row());
else
std::cout << "Error - OnLinkTableDoubleClick() activated by invalid sender\n";
CScriptNode *pLinkedNode = pNode->Scene()->ScriptNodeByID(Link.ObjectID);
if (pLinkedNode)
{
mpWorldEditor->ClearSelection();
mpWorldEditor->SelectNode(pLinkedNode);
}
ui->InLinksTableView->clearSelection();
ui->OutLinksTableView->clearSelection();
}
}

View File

@@ -0,0 +1,47 @@
#ifndef WMODIFYTAB_H
#define WMODIFYTAB_H
#include <QWidget>
#include <QScrollArea>
#include <QTabWidget>
#include <QVBoxLayout>
#include <QMap>
#include "CLinkModel.h"
#include "../WPropertyEditor.h"
#include <Scene/CSceneNode.h>
class CWorldEditor;
namespace Ui {
class WModifyTab;
}
class WModifyTab : public QWidget
{
Q_OBJECT
CWorldEditor *mpWorldEditor;
CSceneNode *mpSelectedNode;
QMap<CScriptTemplate*, WPropertyEditor*> mCachedPropEditors;
WPropertyEditor *mpCurPropEditor;
CLinkModel *mpInLinkModel;
CLinkModel *mpOutLinkModel;
public:
explicit WModifyTab(QWidget *pParent = 0);
~WModifyTab();
void SetEditor(CWorldEditor *pEditor);
void GenerateUI(std::list<CSceneNode*>& Selection);
void ClearUI();
void ClearCachedEditors();
private:
Ui::WModifyTab *ui;
private slots:
void OnLinkTableDoubleClick(QModelIndex Index);
};
#endif // WMODIFYTAB_H

View File

@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WModifyTab</class>
<widget class="QWidget" name="WModifyTab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>282</width>
<height>502</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="MainLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QTabWidget" name="ObjectsTabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="PropertiesTab">
<attribute name="title">
<string>Properties</string>
</attribute>
<layout class="QVBoxLayout" name="PropertiesLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="PropertiesScrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="PropertiesScrollContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>276</width>
<height>439</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="PropertiesScrollLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="ConnectionsTab">
<attribute name="title">
<string>Connections</string>
</attribute>
<layout class="QVBoxLayout" name="ConnectionsLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="ConnectionsScrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="ConnectionsScrollContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>276</width>
<height>439</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="OutLinksGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Outgoing</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QTableView" name="OutLinksTableView">
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>75</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="InLinksGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Incoming</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTableView" name="InLinksTableView">
<attribute name="horizontalHeaderDefaultSectionSize">
<number>75</number>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QGroupBox" name="LightGroupBox">
<property name="title">
<string>Light</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>