mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-18 01:15:26 +00:00
Initial commit of current work on Prime World Editor
This commit is contained in:
5
UI/CDarkStyle.cpp
Normal file
5
UI/CDarkStyle.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "CDarkStyle.h"
|
||||
|
||||
CDarkStyle::CDarkStyle()
|
||||
{
|
||||
}
|
||||
14
UI/CDarkStyle.h
Normal file
14
UI/CDarkStyle.h
Normal 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
247
UI/CEditorGLWidget.cpp
Normal 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
63
UI/CEditorGLWidget.h
Normal 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
14
UI/CMaterialEditor.cpp
Normal 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
22
UI/CMaterialEditor.h
Normal 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
18
UI/CMaterialEditor.ui
Normal 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
795
UI/CModelEditorWindow.cpp
Normal 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
122
UI/CModelEditorWindow.h
Normal 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
2502
UI/CModelEditorWindow.ui
Normal file
File diff suppressed because it is too large
Load Diff
58
UI/CNodeSelection.cpp
Normal file
58
UI/CNodeSelection.cpp
Normal 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
24
UI/CNodeSelection.h
Normal 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
12
UI/CSimpleDelegate.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "CSimpleDelegate.h"
|
||||
|
||||
CSimpleDelegate::CSimpleDelegate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CSimpleDelegate::~CSimpleDelegate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
12
UI/CSimpleDelegate.h
Normal file
12
UI/CSimpleDelegate.h
Normal 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
181
UI/CStartWindow.cpp
Normal 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
46
UI/CStartWindow.h
Normal 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
260
UI/CStartWindow.ui
Normal 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
491
UI/CWorldEditor.cpp
Normal 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
94
UI/CWorldEditor.h
Normal 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
608
UI/CWorldEditor.ui
Normal 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
300
UI/CWorldEditorWindow.cpp
Normal 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
89
UI/CWorldEditorWindow.h
Normal 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
460
UI/CWorldEditorWindow.ui
Normal 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
24
UI/IPreviewPanel.cpp
Normal 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
17
UI/IPreviewPanel.h
Normal 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
22
UI/PWEMaterialEditor.h
Normal 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
22
UI/TestDialog.cpp
Normal 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
22
UI/TestDialog.h
Normal 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
125
UI/TestDialog.ui
Normal 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
46
UI/UICommon.cpp
Normal 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
9
UI/UICommon.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef UICOMMON
|
||||
#define UICOMMON
|
||||
|
||||
#include <QString>
|
||||
|
||||
extern const QString gskResourceFilters[];
|
||||
|
||||
#endif // UICOMMON
|
||||
|
||||
12
UI/WCollapsibleGroupBox.cpp
Normal file
12
UI/WCollapsibleGroupBox.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "WCollapsibleGroupBox.h"
|
||||
|
||||
WCollapsibleGroupBox::WCollapsibleGroupBox()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
WCollapsibleGroupBox::~WCollapsibleGroupBox()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
12
UI/WCollapsibleGroupBox.h
Normal file
12
UI/WCollapsibleGroupBox.h
Normal 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
92
UI/WColorPicker.cpp
Normal 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
28
UI/WColorPicker.h
Normal 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
55
UI/WDraggableSpinBox.cpp
Normal 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
23
UI/WDraggableSpinBox.h
Normal 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
353
UI/WPropertyEditor.cpp
Normal 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
36
UI/WPropertyEditor.h
Normal 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
335
UI/WResourceSelector.cpp
Normal 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
91
UI/WResourceSelector.h
Normal 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
64
UI/WRollout.cpp
Normal 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
29
UI/WRollout.h
Normal 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
75
UI/WScanPreviewPanel.cpp
Normal 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
24
UI/WScanPreviewPanel.h
Normal 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
154
UI/WScanPreviewPanel.ui
Normal 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>
|
||||
52
UI/WStringPreviewPanel.cpp
Normal file
52
UI/WStringPreviewPanel.cpp
Normal 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
24
UI/WStringPreviewPanel.h
Normal 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
156
UI/WTextureGLWidget.cpp
Normal 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
39
UI/WTextureGLWidget.h
Normal 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
|
||||
63
UI/WTexturePreviewPanel.cpp
Normal file
63
UI/WTexturePreviewPanel.cpp
Normal 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
25
UI/WTexturePreviewPanel.h
Normal 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
|
||||
77
UI/WTexturePreviewPanel.ui
Normal file
77
UI/WTexturePreviewPanel.ui
Normal 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
117
UI/WVectorEditor.cpp
Normal 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
43
UI/WVectorEditor.h
Normal 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
|
||||
54
UI/WorldEditor/CLayerEditor.cpp
Normal file
54
UI/WorldEditor/CLayerEditor.cpp
Normal 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);
|
||||
}
|
||||
32
UI/WorldEditor/CLayerEditor.h
Normal file
32
UI/WorldEditor/CLayerEditor.h
Normal 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
|
||||
60
UI/WorldEditor/CLayerEditor.ui
Normal file
60
UI/WorldEditor/CLayerEditor.ui
Normal 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>
|
||||
46
UI/WorldEditor/CLayerModel.cpp
Normal file
46
UI/WorldEditor/CLayerModel.cpp
Normal 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;
|
||||
}
|
||||
21
UI/WorldEditor/CLayerModel.h
Normal file
21
UI/WorldEditor/CLayerModel.h
Normal 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
|
||||
119
UI/WorldEditor/CLayersInstanceModel.cpp
Normal file
119
UI/WorldEditor/CLayersInstanceModel.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
49
UI/WorldEditor/CLayersInstanceModel.h
Normal file
49
UI/WorldEditor/CLayersInstanceModel.h
Normal 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
|
||||
101
UI/WorldEditor/CLinkModel.cpp
Normal file
101
UI/WorldEditor/CLinkModel.cpp
Normal 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;
|
||||
}
|
||||
30
UI/WorldEditor/CLinkModel.h
Normal file
30
UI/WorldEditor/CLinkModel.h
Normal 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
|
||||
451
UI/WorldEditor/CTypesInstanceModel.cpp
Normal file
451
UI/WorldEditor/CTypesInstanceModel.cpp
Normal 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();
|
||||
}
|
||||
67
UI/WorldEditor/CTypesInstanceModel.h
Normal file
67
UI/WorldEditor/CTypesInstanceModel.h
Normal 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
|
||||
14
UI/WorldEditor/WCreateTab.cpp
Normal file
14
UI/WorldEditor/WCreateTab.cpp
Normal 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;
|
||||
}
|
||||
22
UI/WorldEditor/WCreateTab.h
Normal file
22
UI/WorldEditor/WCreateTab.h
Normal 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
|
||||
19
UI/WorldEditor/WCreateTab.ui
Normal file
19
UI/WorldEditor/WCreateTab.ui
Normal 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>
|
||||
163
UI/WorldEditor/WInstancesTab.cpp
Normal file
163
UI/WorldEditor/WInstancesTab.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
51
UI/WorldEditor/WInstancesTab.h
Normal file
51
UI/WorldEditor/WInstancesTab.h
Normal 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
|
||||
74
UI/WorldEditor/WInstancesTab.ui
Normal file
74
UI/WorldEditor/WInstancesTab.ui
Normal 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>
|
||||
145
UI/WorldEditor/WModifyTab.cpp
Normal file
145
UI/WorldEditor/WModifyTab.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
47
UI/WorldEditor/WModifyTab.h
Normal file
47
UI/WorldEditor/WModifyTab.h
Normal 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
|
||||
222
UI/WorldEditor/WModifyTab.ui
Normal file
222
UI/WorldEditor/WModifyTab.ui
Normal 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>
|
||||
Reference in New Issue
Block a user