Feature additions and improvements for pick mode and the POI -> World editor
This commit is contained in:
parent
5c3a37ca4a
commit
440c3ad484
|
@ -5,14 +5,15 @@
|
||||||
|
|
||||||
enum EKeyInput
|
enum EKeyInput
|
||||||
{
|
{
|
||||||
eCtrlKey = 0x1,
|
eCtrlKey = 0x1,
|
||||||
eAltKey = 0x2,
|
eShiftKey = 0x2,
|
||||||
eQKey = 0x4,
|
eAltKey = 0x2,
|
||||||
eWKey = 0x8,
|
eQKey = 0x4,
|
||||||
eEKey = 0x10,
|
eWKey = 0x8,
|
||||||
eAKey = 0x20,
|
eEKey = 0x10,
|
||||||
eSKey = 0x40,
|
eAKey = 0x20,
|
||||||
eDKey = 0x80
|
eSKey = 0x40,
|
||||||
|
eDKey = 0x80
|
||||||
};
|
};
|
||||||
DECLARE_FLAGS(EKeyInput, FKeyInputs)
|
DECLARE_FLAGS(EKeyInput, FKeyInputs)
|
||||||
|
|
||||||
|
|
|
@ -68,10 +68,6 @@ void CPoiToWorld::RemovePoiMeshMap(u32 PoiID, u32 ModelID)
|
||||||
if (*ListIt == ModelID)
|
if (*ListIt == ModelID)
|
||||||
{
|
{
|
||||||
pMap->ModelIDs.erase(ListIt);
|
pMap->ModelIDs.erase(ListIt);
|
||||||
|
|
||||||
if (pMap->ModelIDs.empty())
|
|
||||||
RemovePoi(PoiID);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define SRAYINTERSECTION
|
#define SRAYINTERSECTION
|
||||||
|
|
||||||
#include <Common/types.h>
|
#include <Common/types.h>
|
||||||
|
#include <Math/CVector3f.h>
|
||||||
|
|
||||||
class CSceneNode;
|
class CSceneNode;
|
||||||
|
|
||||||
|
@ -9,12 +10,15 @@ struct SRayIntersection
|
||||||
{
|
{
|
||||||
bool Hit;
|
bool Hit;
|
||||||
float Distance;
|
float Distance;
|
||||||
|
CVector3f HitPoint;
|
||||||
CSceneNode *pNode;
|
CSceneNode *pNode;
|
||||||
u32 ComponentIndex;
|
u32 ComponentIndex;
|
||||||
|
|
||||||
SRayIntersection() {}
|
SRayIntersection()
|
||||||
SRayIntersection(bool _Hit, float _Distance, CSceneNode *_pNode, u32 _ComponentIndex)
|
: Hit(false), Distance(0.f), HitPoint(CVector3f::skZero), pNode(nullptr), ComponentIndex(-1) {}
|
||||||
: Hit(_Hit), Distance(_Distance), pNode(_pNode), ComponentIndex(_ComponentIndex) {}
|
|
||||||
|
SRayIntersection(bool _Hit, float _Distance, CVector3f _HitPoint, CSceneNode *_pNode, u32 _ComponentIndex)
|
||||||
|
: Hit(_Hit), Distance(_Distance), HitPoint(_HitPoint), pNode(_pNode), ComponentIndex(_ComponentIndex) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SRAYINTERSECTION
|
#endif // SRAYINTERSECTION
|
||||||
|
|
|
@ -18,7 +18,7 @@ public:
|
||||||
inline void RayAABoxIntersectTest(CRayCollisionTester&, const SViewInfo&) {}
|
inline void RayAABoxIntersectTest(CRayCollisionTester&, const SViewInfo&) {}
|
||||||
|
|
||||||
inline SRayIntersection RayNodeIntersectTest(const CRay &, u32, const SViewInfo&) {
|
inline SRayIntersection RayNodeIntersectTest(const CRay &, u32, const SViewInfo&) {
|
||||||
return SRayIntersection(false, 0.f, nullptr, 0);
|
return SRayIntersection();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void DrawSelection() {}
|
inline void DrawSelection() {}
|
||||||
|
|
|
@ -250,13 +250,15 @@ void CDamageableTriggerExtra::RayAABoxIntersectTest(CRayCollisionTester& Tester,
|
||||||
std::pair<bool,float> Result = AABox().IntersectsRay(Ray);
|
std::pair<bool,float> Result = AABox().IntersectsRay(Ray);
|
||||||
|
|
||||||
if (Result.first)
|
if (Result.first)
|
||||||
|
{
|
||||||
Tester.AddNode(this, -1, Result.second);
|
Tester.AddNode(this, -1, Result.second);
|
||||||
|
mCachedRayDistance = Result.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SRayIntersection CDamageableTriggerExtra::RayNodeIntersectTest(const CRay& Ray, u32 /*ComponentIndex*/, const SViewInfo& /*ViewInfo*/)
|
SRayIntersection CDamageableTriggerExtra::RayNodeIntersectTest(const CRay& Ray, u32 /*ComponentIndex*/, const SViewInfo& /*ViewInfo*/)
|
||||||
{
|
{
|
||||||
// The bounding box and all other tests already passed in RayAABoxIntersectTest, so we
|
// The bounding box and all other tests already passed in RayAABoxIntersectTest, so we
|
||||||
// already know that we have a positive. We just need the distance again.
|
// already know that we have a positive.
|
||||||
std::pair<bool,float> Result = AABox().IntersectsRay(Ray);
|
return SRayIntersection(true, mCachedRayDistance, Ray.PointOnRay(mCachedRayDistance), mpParent, -1);
|
||||||
return SRayIntersection(true, Result.second, mpParent, -1);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ class CDamageableTriggerExtra : public CScriptExtra
|
||||||
CMaterial *mpMat;
|
CMaterial *mpMat;
|
||||||
CVector2f mCoordScale;
|
CVector2f mCoordScale;
|
||||||
|
|
||||||
|
float mCachedRayDistance;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CDamageableTriggerExtra(CScriptObject *pInstance, CScene *pScene, CSceneNode *pParent = 0);
|
explicit CDamageableTriggerExtra(CScriptObject *pInstance, CScene *pScene, CSceneNode *pParent = 0);
|
||||||
~CDamageableTriggerExtra();
|
~CDamageableTriggerExtra();
|
||||||
|
|
|
@ -144,6 +144,8 @@ void CBasicViewport::keyPressEvent(QKeyEvent *pEvent)
|
||||||
case Qt::Key_S: mKeysPressed |= eSKey; break;
|
case Qt::Key_S: mKeysPressed |= eSKey; break;
|
||||||
case Qt::Key_D: mKeysPressed |= eDKey; break;
|
case Qt::Key_D: mKeysPressed |= eDKey; break;
|
||||||
case Qt::Key_Control: mKeysPressed |= eCtrlKey; break;
|
case Qt::Key_Control: mKeysPressed |= eCtrlKey; break;
|
||||||
|
case Qt::Key_Shift: mKeysPressed |= eShiftKey; break;
|
||||||
|
case Qt::Key_Alt: mKeysPressed |= eAltKey; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +160,8 @@ void CBasicViewport::keyReleaseEvent(QKeyEvent *pEvent)
|
||||||
case Qt::Key_S: mKeysPressed &= ~eSKey; break;
|
case Qt::Key_S: mKeysPressed &= ~eSKey; break;
|
||||||
case Qt::Key_D: mKeysPressed &= ~eDKey; break;
|
case Qt::Key_D: mKeysPressed &= ~eDKey; break;
|
||||||
case Qt::Key_Control: mKeysPressed &= ~eCtrlKey; break;
|
case Qt::Key_Control: mKeysPressed &= ~eCtrlKey; break;
|
||||||
|
case Qt::Key_Shift: mKeysPressed &= ~eShiftKey; break;
|
||||||
|
case Qt::Key_Alt: mKeysPressed &= ~eAltKey; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,13 +208,13 @@ bool CBasicViewport::IsCursorVisible()
|
||||||
|
|
||||||
bool CBasicViewport::IsMouseInputActive()
|
bool CBasicViewport::IsMouseInputActive()
|
||||||
{
|
{
|
||||||
static const int skMoveButtons = eMiddleButton | eRightButton;
|
static const FMouseInputs skMoveButtons = eMiddleButton | eRightButton;
|
||||||
return ((mButtonsPressed & skMoveButtons) != 0);
|
return ((mButtonsPressed & skMoveButtons) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBasicViewport::IsKeyboardInputActive()
|
bool CBasicViewport::IsKeyboardInputActive()
|
||||||
{
|
{
|
||||||
static const int skMoveKeys = eQKey | eWKey | eEKey | eAKey | eSKey | eDKey;
|
static const FKeyInputs skMoveKeys = eQKey | eWKey | eEKey | eAKey | eSKey | eDKey;
|
||||||
return ((mKeysPressed & skMoveKeys) != 0);
|
return ((mKeysPressed & skMoveKeys) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,8 @@ protected:
|
||||||
QPoint mLastMousePos;
|
QPoint mLastMousePos;
|
||||||
bool mMouseMoved;
|
bool mMouseMoved;
|
||||||
CTimer mMoveTimer;
|
CTimer mMoveTimer;
|
||||||
int mButtonsPressed; // int container for EMouseInputs flags
|
FMouseInputs mButtonsPressed;
|
||||||
int mKeysPressed; // int container for EKeyInputs flags
|
FKeyInputs mKeysPressed;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CBasicViewport(QWidget *pParent = 0);
|
explicit CBasicViewport(QWidget *pParent = 0);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <Core/Render/SViewInfo.h>
|
#include <Core/Render/SViewInfo.h>
|
||||||
#include <Core/Resource/Script/CScriptLayer.h>
|
#include <Core/Resource/Script/CScriptLayer.h>
|
||||||
#include <Core/Scene/CSceneIterator.h>
|
#include <Core/Scene/CSceneIterator.h>
|
||||||
|
#include <QApplication>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
|
||||||
CSceneViewport::CSceneViewport(QWidget *pParent)
|
CSceneViewport::CSceneViewport(QWidget *pParent)
|
||||||
|
@ -109,7 +110,7 @@ void CSceneViewport::CheckGizmoInput(const CRay& ray)
|
||||||
else mGizmoHovering = false;
|
else mGizmoHovering = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSceneViewport::SceneRayCast(const CRay& ray)
|
void CSceneViewport::SceneRayCast(const CRay& rkRay)
|
||||||
{
|
{
|
||||||
if (mpEditor->Gizmo()->IsTransforming())
|
if (mpEditor->Gizmo()->IsTransforming())
|
||||||
{
|
{
|
||||||
|
@ -117,16 +118,16 @@ void CSceneViewport::SceneRayCast(const CRay& ray)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRayIntersection result = mpScene->SceneRayCast(ray, mViewInfo);
|
mRayIntersection = mpScene->SceneRayCast(rkRay, mViewInfo);
|
||||||
|
|
||||||
if (result.Hit)
|
if (mRayIntersection.Hit)
|
||||||
{
|
{
|
||||||
if (mpHoverNode)
|
if (mpHoverNode)
|
||||||
mpHoverNode->SetMouseHovering(false);
|
mpHoverNode->SetMouseHovering(false);
|
||||||
|
|
||||||
mpHoverNode = result.pNode;
|
mpHoverNode = mRayIntersection.pNode;
|
||||||
mpHoverNode->SetMouseHovering(true);
|
mpHoverNode->SetMouseHovering(true);
|
||||||
mHoverPoint = ray.PointOnRay(result.Distance);
|
mHoverPoint = rkRay.PointOnRay(mRayIntersection.Distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
|
@ -210,6 +211,11 @@ void CSceneViewport::CreateContextMenu()
|
||||||
mpContextMenu->addActions(Actions);
|
mpContextMenu->addActions(Actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMouseEvent CSceneViewport::CreateMouseEvent()
|
||||||
|
{
|
||||||
|
return QMouseEvent(QEvent::MouseMove, mapFromGlobal(QCursor::pos()), Qt::NoButton, qApp->mouseButtons(), qApp->keyboardModifiers());
|
||||||
|
}
|
||||||
|
|
||||||
// ************ PROTECTED SLOTS ************
|
// ************ PROTECTED SLOTS ************
|
||||||
void CSceneViewport::CheckUserInput()
|
void CSceneViewport::CheckUserInput()
|
||||||
{
|
{
|
||||||
|
@ -219,18 +225,24 @@ void CSceneViewport::CheckUserInput()
|
||||||
{
|
{
|
||||||
ResetHover();
|
ResetHover();
|
||||||
mGizmoHovering = false;
|
mGizmoHovering = false;
|
||||||
|
|
||||||
if (!MouseActive)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CRay ray = CastRay();
|
if (MouseActive)
|
||||||
|
{
|
||||||
|
CRay Ray = CastRay();
|
||||||
|
|
||||||
if (!mViewInfo.GameMode)
|
if (!mViewInfo.GameMode)
|
||||||
CheckGizmoInput(ray);
|
CheckGizmoInput(Ray);
|
||||||
|
|
||||||
if (!mpEditor->Gizmo()->IsTransforming())
|
if (!mpEditor->Gizmo()->IsTransforming())
|
||||||
SceneRayCast(ray);
|
SceneRayCast(Ray);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
mRayIntersection = SRayIntersection();
|
||||||
|
|
||||||
|
QMouseEvent Event = CreateMouseEvent();
|
||||||
|
emit InputProcessed(mRayIntersection, &Event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSceneViewport::Paint()
|
void CSceneViewport::Paint()
|
||||||
|
@ -346,7 +358,7 @@ void CSceneViewport::OnMouseRelease(QMouseEvent *pEvent)
|
||||||
|
|
||||||
// Object selection/deselection
|
// Object selection/deselection
|
||||||
else
|
else
|
||||||
emit ViewportClick(mpHoverNode, pEvent);
|
emit ViewportClick(mRayIntersection, pEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ class CSceneViewport : public CBasicViewport
|
||||||
// Scene interaction
|
// Scene interaction
|
||||||
bool mGizmoHovering;
|
bool mGizmoHovering;
|
||||||
bool mGizmoTransforming;
|
bool mGizmoTransforming;
|
||||||
|
SRayIntersection mRayIntersection;
|
||||||
CSceneNode *mpHoverNode;
|
CSceneNode *mpHoverNode;
|
||||||
CVector3f mHoverPoint;
|
CVector3f mHoverPoint;
|
||||||
|
|
||||||
|
@ -54,9 +55,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void CreateContextMenu();
|
void CreateContextMenu();
|
||||||
|
QMouseEvent CreateMouseEvent();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void ViewportClick(CSceneNode *pNode, QMouseEvent *pEvent);
|
void InputProcessed(const SRayIntersection& rkIntersect, QMouseEvent *pEvent);
|
||||||
|
void ViewportClick(const SRayIntersection& rkIntersect, QMouseEvent *pEvent);
|
||||||
void GizmoMoved();
|
void GizmoMoved();
|
||||||
void CameraOrbit();
|
void CameraOrbit();
|
||||||
|
|
||||||
|
|
|
@ -209,7 +209,7 @@ const QList<CSceneNode*>& INodeEditor::GetSelection() const
|
||||||
return mSelection;
|
return mSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void INodeEditor::EnterPickMode(FNodeFlags AllowedNodes, bool ExitOnInvalidPick, bool EmitOnInvalidPick, QCursor Cursor /*= Qt::CrossCursor*/)
|
void INodeEditor::EnterPickMode(FNodeFlags AllowedNodes, bool ExitOnInvalidPick, bool EmitOnInvalidPick, bool EmitHoverOnButtonPress, QCursor Cursor /*= Qt::CrossCursor*/)
|
||||||
{
|
{
|
||||||
// If we're already in pick mode, exit first so the previous caller has a chance to disconnect
|
// If we're already in pick mode, exit first so the previous caller has a chance to disconnect
|
||||||
if (mPickMode)
|
if (mPickMode)
|
||||||
|
@ -219,6 +219,7 @@ void INodeEditor::EnterPickMode(FNodeFlags AllowedNodes, bool ExitOnInvalidPick,
|
||||||
mAllowedPickNodes = AllowedNodes;
|
mAllowedPickNodes = AllowedNodes;
|
||||||
mExitOnInvalidPick = ExitOnInvalidPick;
|
mExitOnInvalidPick = ExitOnInvalidPick;
|
||||||
mEmitOnInvalidPick = EmitOnInvalidPick;
|
mEmitOnInvalidPick = EmitOnInvalidPick;
|
||||||
|
mEmitOnButtonPress = EmitHoverOnButtonPress;
|
||||||
emit PickModeEntered(Cursor);
|
emit PickModeEntered(Cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,12 +264,14 @@ void INodeEditor::OnGizmoMoved()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ PROTECTED SLOTS ************
|
// ************ PROTECTED SLOTS ************
|
||||||
void INodeEditor::OnViewportClick(CSceneNode *pHoverNode, QMouseEvent *pEvent)
|
void INodeEditor::OnViewportClick(const SRayIntersection& rkRayIntersect, QMouseEvent *pEvent)
|
||||||
{
|
{
|
||||||
|
CSceneNode *pNode = rkRayIntersect.pNode;
|
||||||
|
|
||||||
// Not in pick mode: process node selection/deselection
|
// Not in pick mode: process node selection/deselection
|
||||||
if (!mPickMode)
|
if (!mPickMode)
|
||||||
{
|
{
|
||||||
bool ValidNode = (pHoverNode && (pHoverNode->NodeType() & mSelectionNodeFlags));
|
bool ValidNode = (pNode && (pNode->NodeType() & mSelectionNodeFlags));
|
||||||
bool AltPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
bool AltPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
||||||
bool CtrlPressed = ((pEvent->modifiers() & Qt::ControlModifier) != 0);
|
bool CtrlPressed = ((pEvent->modifiers() & Qt::ControlModifier) != 0);
|
||||||
|
|
||||||
|
@ -278,14 +281,14 @@ void INodeEditor::OnViewportClick(CSceneNode *pHoverNode, QMouseEvent *pEvent)
|
||||||
if (!ValidNode)
|
if (!ValidNode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DeselectNode(pHoverNode);
|
DeselectNode(pNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ctrl: Add to selection
|
// Ctrl: Add to selection
|
||||||
else if (CtrlPressed)
|
else if (CtrlPressed)
|
||||||
{
|
{
|
||||||
if (ValidNode)
|
if (ValidNode)
|
||||||
SelectNode(pHoverNode);
|
SelectNode(pNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Neither: clear selection + select
|
// Neither: clear selection + select
|
||||||
|
@ -294,7 +297,7 @@ void INodeEditor::OnViewportClick(CSceneNode *pHoverNode, QMouseEvent *pEvent)
|
||||||
if (!mGizmoHovering)
|
if (!mGizmoHovering)
|
||||||
{
|
{
|
||||||
if (ValidNode)
|
if (ValidNode)
|
||||||
ClearAndSelectNode(pHoverNode);
|
ClearAndSelectNode(pNode);
|
||||||
else
|
else
|
||||||
ClearSelection();
|
ClearSelection();
|
||||||
}
|
}
|
||||||
|
@ -306,16 +309,43 @@ void INodeEditor::OnViewportClick(CSceneNode *pHoverNode, QMouseEvent *pEvent)
|
||||||
// In pick mode: process node pick
|
// In pick mode: process node pick
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool ValidNode = (pHoverNode && (pHoverNode->NodeType() & mAllowedPickNodes));
|
bool ValidNode = (pNode && (pNode->NodeType() & mAllowedPickNodes));
|
||||||
|
|
||||||
if (ValidNode || mEmitOnInvalidPick)
|
if (ValidNode || mEmitOnInvalidPick)
|
||||||
emit PickModeClick(pHoverNode, pEvent);
|
emit PickModeClick(rkRayIntersect, pEvent);
|
||||||
|
|
||||||
if (!ValidNode && mExitOnInvalidPick)
|
if (!ValidNode && mExitOnInvalidPick)
|
||||||
ExitPickMode();
|
ExitPickMode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void INodeEditor::OnViewportInputProcessed(const SRayIntersection& rkRayIntersect, QMouseEvent *pEvent)
|
||||||
|
{
|
||||||
|
// In pick mode: process node hover
|
||||||
|
if (mPickMode)
|
||||||
|
{
|
||||||
|
CSceneNode *pNode = rkRayIntersect.pNode;
|
||||||
|
bool NewNode = pNode != mpPickHoverNode;
|
||||||
|
|
||||||
|
bool ButtonsChanged = mPickButtons != pEvent->buttons();
|
||||||
|
bool ModifiersChanged = mPickModifiers != pEvent->modifiers();
|
||||||
|
|
||||||
|
if (NewNode || ((ModifiersChanged || ButtonsChanged) && mEmitOnButtonPress))
|
||||||
|
{
|
||||||
|
bool ValidNode = (pNode && (pNode->NodeType() & mAllowedPickNodes));
|
||||||
|
|
||||||
|
if (ValidNode || mEmitOnInvalidPick)
|
||||||
|
emit PickModeHoverChanged(rkRayIntersect, pEvent);
|
||||||
|
else
|
||||||
|
emit PickModeHoverChanged(SRayIntersection(), pEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpPickHoverNode = rkRayIntersect.pNode;
|
||||||
|
mPickButtons = pEvent->buttons();
|
||||||
|
mPickModifiers = pEvent->modifiers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ************ PRIVATE ************
|
// ************ PRIVATE ************
|
||||||
void INodeEditor::UpdateTransformActionsEnabled()
|
void INodeEditor::UpdateTransformActionsEnabled()
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,7 +45,11 @@ protected:
|
||||||
bool mPickMode;
|
bool mPickMode;
|
||||||
bool mExitOnInvalidPick;
|
bool mExitOnInvalidPick;
|
||||||
bool mEmitOnInvalidPick;
|
bool mEmitOnInvalidPick;
|
||||||
|
bool mEmitOnButtonPress;
|
||||||
FNodeFlags mAllowedPickNodes;
|
FNodeFlags mAllowedPickNodes;
|
||||||
|
CSceneNode *mpPickHoverNode;
|
||||||
|
Qt::MouseButtons mPickButtons;
|
||||||
|
Qt::KeyboardModifiers mPickModifiers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit INodeEditor(QWidget *pParent = 0);
|
explicit INodeEditor(QWidget *pParent = 0);
|
||||||
|
@ -70,7 +74,7 @@ public:
|
||||||
bool HasSelection() const;
|
bool HasSelection() const;
|
||||||
const QList<CSceneNode*>& GetSelection() const;
|
const QList<CSceneNode*>& GetSelection() const;
|
||||||
|
|
||||||
void EnterPickMode(FNodeFlags AllowedNodes, bool ExitOnInvalidPick, bool EmitOnInvalidPick, QCursor Cursor = Qt::CrossCursor);
|
void EnterPickMode(FNodeFlags AllowedNodes, bool ExitOnInvalidPick, bool EmitOnInvalidPick, bool EmitHoverOnButtonPress, QCursor Cursor = Qt::CrossCursor);
|
||||||
void ExitPickMode();
|
void ExitPickMode();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -79,7 +83,8 @@ signals:
|
||||||
|
|
||||||
void PickModeEntered(QCursor Cursor);
|
void PickModeEntered(QCursor Cursor);
|
||||||
void PickModeExited();
|
void PickModeExited();
|
||||||
void PickModeClick(CSceneNode *pNode, QMouseEvent *pEvent);
|
void PickModeClick(const SRayIntersection& rkRayIntersect, QMouseEvent *pEvent);
|
||||||
|
void PickModeHoverChanged(const SRayIntersection& rkRayIntersect, QMouseEvent *pEvent);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void OnGizmoMoved();
|
void OnGizmoMoved();
|
||||||
|
@ -90,7 +95,8 @@ protected:
|
||||||
virtual void GizmoModeChanged(CGizmo::EGizmoMode /*mode*/) {}
|
virtual void GizmoModeChanged(CGizmo::EGizmoMode /*mode*/) {}
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void OnViewportClick(CSceneNode *pHoverNode, QMouseEvent *pEvent);
|
void OnViewportClick(const SRayIntersection& rkRayIntersect, QMouseEvent *pEvent);
|
||||||
|
void OnViewportInputProcessed(const SRayIntersection& rkRayIntersect, QMouseEvent *pEvent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateTransformActionsEnabled();
|
void UpdateTransformActionsEnabled();
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
const CColor CPoiMapEditDialog::skNormalColor(0.137255f, 0.184314f, 0.776471f, 0.5f);
|
const CColor CPoiMapEditDialog::skNormalColor(0.137255f, 0.184314f, 0.776471f, 0.5f);
|
||||||
const CColor CPoiMapEditDialog::skImportantColor(0.721569f, 0.066667f, 0.066667f, 0.5f);
|
const CColor CPoiMapEditDialog::skImportantColor(0.721569f, 0.066667f, 0.066667f, 0.5f);
|
||||||
|
const CColor CPoiMapEditDialog::skHoverColor(0.047059f, 0.2f, 0.003922f, 0.5f);
|
||||||
|
|
||||||
CPoiMapEditDialog::CPoiMapEditDialog(CWorldEditor *pEditor, QWidget *parent)
|
CPoiMapEditDialog::CPoiMapEditDialog(CWorldEditor *pEditor, QWidget *parent)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
|
@ -20,12 +21,16 @@ CPoiMapEditDialog::CPoiMapEditDialog(CWorldEditor *pEditor, QWidget *parent)
|
||||||
, mSourceModel(pEditor, this)
|
, mSourceModel(pEditor, this)
|
||||||
, mHighlightMode(eHighlightSelected)
|
, mHighlightMode(eHighlightSelected)
|
||||||
, mPickType(eNotPicking)
|
, mPickType(eNotPicking)
|
||||||
|
, mPickTool(eNormalTool)
|
||||||
|
, mHoverModelIsMapped(false)
|
||||||
|
, mpHoverModel(nullptr)
|
||||||
{
|
{
|
||||||
mModel.setSourceModel(&mSourceModel);
|
mModel.setSourceModel(&mSourceModel);
|
||||||
mModel.sort(0);
|
mModel.sort(0);
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->ListView->setModel(&mModel);
|
ui->ListView->setModel(&mModel);
|
||||||
|
ui->ListView->selectionModel()->select(mModel.index(0,0), QItemSelectionModel::Select | QItemSelectionModel::Current);
|
||||||
|
|
||||||
QActionGroup *pGroup = new QActionGroup(this);
|
QActionGroup *pGroup = new QActionGroup(this);
|
||||||
pGroup->addAction(ui->ActionHighlightSelected);
|
pGroup->addAction(ui->ActionHighlightSelected);
|
||||||
|
@ -41,8 +46,8 @@ CPoiMapEditDialog::CPoiMapEditDialog(CWorldEditor *pEditor, QWidget *parent)
|
||||||
connect(ui->ListView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnItemDoubleClick(QModelIndex)));
|
connect(ui->ListView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnItemDoubleClick(QModelIndex)));
|
||||||
connect(ui->AddMeshButton, SIGNAL(clicked()), this, SLOT(PickButtonClicked()));
|
connect(ui->AddMeshButton, SIGNAL(clicked()), this, SLOT(PickButtonClicked()));
|
||||||
connect(ui->RemoveMeshButton, SIGNAL(clicked()), this, SLOT(PickButtonClicked()));
|
connect(ui->RemoveMeshButton, SIGNAL(clicked()), this, SLOT(PickButtonClicked()));
|
||||||
connect(ui->ButtonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(close()));
|
connect(ui->ToolComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnToolComboBoxChanged(int)));
|
||||||
connect(ui->ButtonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(close()));
|
connect(ui->ButtonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(close()));
|
||||||
connect(ui->ButtonBox->button(QDialogButtonBox::Save), SIGNAL(clicked()), this, SLOT(Save()));
|
connect(ui->ButtonBox->button(QDialogButtonBox::Save), SIGNAL(clicked()), this, SLOT(Save()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,6 +108,54 @@ void CPoiMapEditDialog::UnhighlightModel(CModelNode *pNode)
|
||||||
pNode->SetScanOverlayEnabled(false);
|
pNode->SetScanOverlayEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPoiMapEditDialog::RevertHoverModelOverlay()
|
||||||
|
{
|
||||||
|
if (mpHoverModel)
|
||||||
|
{
|
||||||
|
if (mHighlightMode == eHighlightAll)
|
||||||
|
{
|
||||||
|
for (int iRow = 0; iRow < mSourceModel.rowCount(QModelIndex()); iRow++)
|
||||||
|
{
|
||||||
|
QModelIndex Index = mSourceModel.index(iRow, 0);
|
||||||
|
|
||||||
|
if (mSourceModel.IsModelMapped(Index, mpHoverModel))
|
||||||
|
{
|
||||||
|
HighlightModel(Index, mpHoverModel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnhighlightModel(mpHoverModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (mHighlightMode == eHighlightSelected)
|
||||||
|
{
|
||||||
|
QModelIndex Index = GetSelectedRow();
|
||||||
|
|
||||||
|
if (mSourceModel.IsModelMapped(Index, mpHoverModel))
|
||||||
|
{
|
||||||
|
HighlightModel(Index, mpHoverModel);
|
||||||
|
mHoverModelIsMapped = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UnhighlightModel(mpHoverModel);
|
||||||
|
mHoverModelIsMapped = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
UnhighlightModel(mpHoverModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CPoiMapEditDialog::EPickType CPoiMapEditDialog::GetRealPickType(bool AltPressed) const
|
||||||
|
{
|
||||||
|
if (!AltPressed) return mPickType;
|
||||||
|
if (mPickType == eAddMeshes) return eRemoveMeshes;
|
||||||
|
return eAddMeshes;
|
||||||
|
}
|
||||||
|
|
||||||
bool CPoiMapEditDialog::IsImportant(const QModelIndex& rkIndex)
|
bool CPoiMapEditDialog::IsImportant(const QModelIndex& rkIndex)
|
||||||
{
|
{
|
||||||
CScriptNode *pPOI = mSourceModel.PoiNodePointer(rkIndex);
|
CScriptNode *pPOI = mSourceModel.PoiNodePointer(rkIndex);
|
||||||
|
@ -116,6 +169,12 @@ bool CPoiMapEditDialog::IsImportant(const QModelIndex& rkIndex)
|
||||||
return Important;
|
return Important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QModelIndex CPoiMapEditDialog::GetSelectedRow() const
|
||||||
|
{
|
||||||
|
QModelIndexList Indices = ui->ListView->selectionModel()->selectedRows();
|
||||||
|
return ( Indices.isEmpty() ? QModelIndex() : mModel.mapToSource(Indices.front()) );
|
||||||
|
}
|
||||||
|
|
||||||
void CPoiMapEditDialog::Save()
|
void CPoiMapEditDialog::Save()
|
||||||
{
|
{
|
||||||
CPoiToWorld *pPoiToWorld = mpEditor->ActiveArea()->GetPoiToWorldMap();
|
CPoiToWorld *pPoiToWorld = mpEditor->ActiveArea()->GetPoiToWorldMap();
|
||||||
|
@ -135,17 +194,27 @@ void CPoiMapEditDialog::Save()
|
||||||
void CPoiMapEditDialog::SetHighlightSelected()
|
void CPoiMapEditDialog::SetHighlightSelected()
|
||||||
{
|
{
|
||||||
const QItemSelection kSelection = ui->ListView->selectionModel()->selection();
|
const QItemSelection kSelection = ui->ListView->selectionModel()->selection();
|
||||||
|
QList<QModelIndex> SelectedIndices;
|
||||||
|
QList<QModelIndex> UnselectedIndices;
|
||||||
|
|
||||||
for (int iRow = 0; iRow < mModel.rowCount(QModelIndex()); iRow++)
|
for (int iRow = 0; iRow < mModel.rowCount(QModelIndex()); iRow++)
|
||||||
{
|
{
|
||||||
QModelIndex Index = mModel.index(iRow, 0);
|
QModelIndex Index = mModel.index(iRow, 0);
|
||||||
|
|
||||||
if (kSelection.contains(Index))
|
if (kSelection.contains(Index))
|
||||||
HighlightPoiModels(Index);
|
SelectedIndices << Index;
|
||||||
else
|
else
|
||||||
UnhighlightPoiModels(Index);
|
UnselectedIndices << Index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int iIdx = 0; iIdx < UnselectedIndices.size(); iIdx++)
|
||||||
|
UnhighlightPoiModels(UnselectedIndices[iIdx]);
|
||||||
|
for (int iIdx = 0; iIdx < SelectedIndices.size(); iIdx++)
|
||||||
|
HighlightPoiModels(SelectedIndices[iIdx]);
|
||||||
|
|
||||||
|
if (mpHoverModel && !mHoverModelIsMapped)
|
||||||
|
HighlightModel(GetSelectedRow(), mpHoverModel);
|
||||||
|
|
||||||
mHighlightMode = eHighlightSelected;
|
mHighlightMode = eHighlightSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +223,13 @@ void CPoiMapEditDialog::SetHighlightAll()
|
||||||
for (int iRow = 0; iRow < mModel.rowCount(QModelIndex()); iRow++)
|
for (int iRow = 0; iRow < mModel.rowCount(QModelIndex()); iRow++)
|
||||||
HighlightPoiModels(mModel.index(iRow, 0));
|
HighlightPoiModels(mModel.index(iRow, 0));
|
||||||
|
|
||||||
|
// Call HighlightPoiModels again on the selected index to prioritize it over the non-selected POIs.
|
||||||
|
if (ui->ListView->selectionModel()->hasSelection())
|
||||||
|
HighlightPoiModels(ui->ListView->selectionModel()->selectedRows().front());
|
||||||
|
|
||||||
|
if (mpHoverModel)
|
||||||
|
HighlightModel(GetSelectedRow(), mpHoverModel);
|
||||||
|
|
||||||
mHighlightMode = eHighlightAll;
|
mHighlightMode = eHighlightAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,6 +238,9 @@ void CPoiMapEditDialog::SetHighlightNone()
|
||||||
for (int iRow = 0; iRow < mModel.rowCount(QModelIndex()); iRow++)
|
for (int iRow = 0; iRow < mModel.rowCount(QModelIndex()); iRow++)
|
||||||
UnhighlightPoiModels(mModel.index(iRow, 0));
|
UnhighlightPoiModels(mModel.index(iRow, 0));
|
||||||
|
|
||||||
|
if (mpHoverModel)
|
||||||
|
UnhighlightModel(mpHoverModel);
|
||||||
|
|
||||||
mHighlightMode = eHighlightNone;
|
mHighlightMode = eHighlightNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,6 +269,14 @@ void CPoiMapEditDialog::OnItemDoubleClick(QModelIndex Index)
|
||||||
mpEditor->ClearAndSelectNode(pPOI);
|
mpEditor->ClearAndSelectNode(pPOI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPoiMapEditDialog::OnToolComboBoxChanged(int NewIndex)
|
||||||
|
{
|
||||||
|
if (NewIndex == 0)
|
||||||
|
mPickTool = eNormalTool;
|
||||||
|
else
|
||||||
|
mPickTool = eSprayCanTool;
|
||||||
|
}
|
||||||
|
|
||||||
void CPoiMapEditDialog::PickButtonClicked()
|
void CPoiMapEditDialog::PickButtonClicked()
|
||||||
{
|
{
|
||||||
QPushButton *pButton = qobject_cast<QPushButton*>(sender());
|
QPushButton *pButton = qobject_cast<QPushButton*>(sender());
|
||||||
|
@ -199,9 +286,10 @@ void CPoiMapEditDialog::PickButtonClicked()
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mpEditor->EnterPickMode(eModelNode, false, false);
|
mpEditor->EnterPickMode(eModelNode, false, false, true);
|
||||||
connect(mpEditor, SIGNAL(PickModeExited()), this, SLOT(StopPicking()));
|
connect(mpEditor, SIGNAL(PickModeExited()), this, SLOT(StopPicking()));
|
||||||
connect(mpEditor, SIGNAL(PickModeClick(CSceneNode*,QMouseEvent*)), this, SLOT(OnNodePicked(CSceneNode*,QMouseEvent*)));
|
connect(mpEditor, SIGNAL(PickModeClick(SRayIntersection,QMouseEvent*)), this, SLOT(OnNodePicked(SRayIntersection,QMouseEvent*)));
|
||||||
|
connect(mpEditor, SIGNAL(PickModeHoverChanged(SRayIntersection,QMouseEvent*)), this, SLOT(OnNodeHover(SRayIntersection,QMouseEvent*)));
|
||||||
pButton->setChecked(true);
|
pButton->setChecked(true);
|
||||||
|
|
||||||
if (pButton == ui->AddMeshButton)
|
if (pButton == ui->AddMeshButton)
|
||||||
|
@ -224,11 +312,16 @@ void CPoiMapEditDialog::StopPicking()
|
||||||
ui->RemoveMeshButton->setChecked(false);
|
ui->RemoveMeshButton->setChecked(false);
|
||||||
mPickType = eNotPicking;
|
mPickType = eNotPicking;
|
||||||
|
|
||||||
|
RevertHoverModelOverlay();
|
||||||
|
mpHoverModel = nullptr;
|
||||||
|
|
||||||
disconnect(mpEditor, 0, this, 0);
|
disconnect(mpEditor, 0, this, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPoiMapEditDialog::OnNodePicked(CSceneNode *pNode, QMouseEvent* pEvent)
|
void CPoiMapEditDialog::OnNodePicked(const SRayIntersection& rkRayIntersect, QMouseEvent* pEvent)
|
||||||
{
|
{
|
||||||
|
if (!rkRayIntersect.pNode) return;
|
||||||
|
|
||||||
// Check for valid selection
|
// Check for valid selection
|
||||||
QModelIndexList Indices = ui->ListView->selectionModel()->selectedRows();
|
QModelIndexList Indices = ui->ListView->selectionModel()->selectedRows();
|
||||||
if (Indices.isEmpty()) return;
|
if (Indices.isEmpty()) return;
|
||||||
|
@ -239,13 +332,10 @@ void CPoiMapEditDialog::OnNodePicked(CSceneNode *pNode, QMouseEvent* pEvent)
|
||||||
SourceIndices << mModel.mapToSource(*it);
|
SourceIndices << mModel.mapToSource(*it);
|
||||||
|
|
||||||
// If alt is pressed, invert the pick mode
|
// If alt is pressed, invert the pick mode
|
||||||
CModelNode *pModel = static_cast<CModelNode*>(pNode);
|
CModelNode *pModel = static_cast<CModelNode*>(rkRayIntersect.pNode);
|
||||||
bool AltPressed = (pEvent->modifiers() & Qt::AltModifier) != 0;
|
|
||||||
|
|
||||||
EPickType PickType;
|
bool AltPressed = (pEvent->modifiers() & Qt::AltModifier) != 0;
|
||||||
if (!AltPressed) PickType = mPickType;
|
EPickType PickType = GetRealPickType(AltPressed);
|
||||||
else if (mPickType == eAddMeshes) PickType = eRemoveMeshes;
|
|
||||||
else PickType = eAddMeshes;
|
|
||||||
|
|
||||||
// Add meshes
|
// Add meshes
|
||||||
if (PickType == eAddMeshes)
|
if (PickType == eAddMeshes)
|
||||||
|
@ -255,6 +345,8 @@ void CPoiMapEditDialog::OnNodePicked(CSceneNode *pNode, QMouseEvent* pEvent)
|
||||||
|
|
||||||
if (mHighlightMode != eHighlightNone)
|
if (mHighlightMode != eHighlightNone)
|
||||||
HighlightModel(SourceIndices.front(), pModel);
|
HighlightModel(SourceIndices.front(), pModel);
|
||||||
|
|
||||||
|
mHoverModelIsMapped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove meshes
|
// Remove meshes
|
||||||
|
@ -264,6 +356,41 @@ void CPoiMapEditDialog::OnNodePicked(CSceneNode *pNode, QMouseEvent* pEvent)
|
||||||
mSourceModel.RemoveMapping(*it, pModel);
|
mSourceModel.RemoveMapping(*it, pModel);
|
||||||
|
|
||||||
if (mHighlightMode != eHighlightNone)
|
if (mHighlightMode != eHighlightNone)
|
||||||
|
RevertHoverModelOverlay();
|
||||||
|
else
|
||||||
UnhighlightModel(pModel);
|
UnhighlightModel(pModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPoiMapEditDialog::OnNodeHover(const SRayIntersection& rkIntersect, QMouseEvent *pEvent)
|
||||||
|
{
|
||||||
|
// Restore old hover model to correct overlay color, and set new hover model
|
||||||
|
if (mpHoverModel)
|
||||||
|
RevertHoverModelOverlay();
|
||||||
|
|
||||||
|
mpHoverModel = static_cast<CModelNode*>(rkIntersect.pNode);
|
||||||
|
|
||||||
|
// If we're using the spray can and the mouse is pressed, treat this as a click.
|
||||||
|
if (mPickTool == eSprayCanTool && (pEvent->buttons() & Qt::LeftButton))
|
||||||
|
OnNodePicked(rkIntersect, pEvent);
|
||||||
|
|
||||||
|
// Otherwise, process as a mouseover
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QModelIndex Index = GetSelectedRow();
|
||||||
|
|
||||||
|
// Process new hover model
|
||||||
|
if (mpHoverModel)
|
||||||
|
{
|
||||||
|
bool AltPressed = (pEvent->modifiers() & Qt::AltModifier) != 0;
|
||||||
|
EPickType PickType = GetRealPickType(AltPressed);
|
||||||
|
|
||||||
|
if ( ((PickType == eAddMeshes) && !mSourceModel.IsModelMapped(Index, mpHoverModel)) ||
|
||||||
|
((PickType == eRemoveMeshes) && mSourceModel.IsModelMapped(Index, mpHoverModel)) )
|
||||||
|
{
|
||||||
|
mpHoverModel->SetScanOverlayEnabled(true);
|
||||||
|
mpHoverModel->SetScanOverlayColor(skHoverColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -35,8 +35,18 @@ class CPoiMapEditDialog : public QMainWindow
|
||||||
eAddPOIs
|
eAddPOIs
|
||||||
} mPickType;
|
} mPickType;
|
||||||
|
|
||||||
|
enum EPickTool
|
||||||
|
{
|
||||||
|
eNormalTool,
|
||||||
|
eSprayCanTool
|
||||||
|
} mPickTool;
|
||||||
|
|
||||||
|
bool mHoverModelIsMapped;
|
||||||
|
CModelNode *mpHoverModel;
|
||||||
|
|
||||||
static const CColor skNormalColor;
|
static const CColor skNormalColor;
|
||||||
static const CColor skImportantColor;
|
static const CColor skImportantColor;
|
||||||
|
static const CColor skHoverColor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CPoiMapEditDialog(CWorldEditor *pEditor, QWidget *parent = 0);
|
explicit CPoiMapEditDialog(CWorldEditor *pEditor, QWidget *parent = 0);
|
||||||
|
@ -46,8 +56,10 @@ public:
|
||||||
void UnhighlightPoiModels(const QModelIndex& rkIndex);
|
void UnhighlightPoiModels(const QModelIndex& rkIndex);
|
||||||
void HighlightModel(const QModelIndex& rkIndex, CModelNode *pNode);
|
void HighlightModel(const QModelIndex& rkIndex, CModelNode *pNode);
|
||||||
void UnhighlightModel(CModelNode *pNode);
|
void UnhighlightModel(CModelNode *pNode);
|
||||||
void RefreshHighlights();
|
|
||||||
bool IsImportant(const QModelIndex& rkIndex);
|
bool IsImportant(const QModelIndex& rkIndex);
|
||||||
|
void RevertHoverModelOverlay();
|
||||||
|
EPickType GetRealPickType(bool AltPressed) const;
|
||||||
|
QModelIndex GetSelectedRow() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void Save();
|
void Save();
|
||||||
|
@ -56,10 +68,12 @@ public slots:
|
||||||
void SetHighlightNone();
|
void SetHighlightNone();
|
||||||
void OnSelectionChanged(const QItemSelection& rkSelected, const QItemSelection& rkDeselected);
|
void OnSelectionChanged(const QItemSelection& rkSelected, const QItemSelection& rkDeselected);
|
||||||
void OnItemDoubleClick(QModelIndex Index);
|
void OnItemDoubleClick(QModelIndex Index);
|
||||||
|
void OnToolComboBoxChanged(int NewIndex);
|
||||||
|
|
||||||
void PickButtonClicked();
|
void PickButtonClicked();
|
||||||
void StopPicking();
|
void StopPicking();
|
||||||
void OnNodePicked(CSceneNode *pNode, QMouseEvent *pEvent);
|
void OnNodePicked(const SRayIntersection& rkIntersect, QMouseEvent *pEvent);
|
||||||
|
void OnNodeHover(const SRayIntersection& rkIntersect, QMouseEvent *pEvent);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Closed();
|
void Closed();
|
||||||
|
|
|
@ -15,19 +15,6 @@
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
|
||||||
<widget class="QListView" name="ListView">
|
|
||||||
<property name="editTriggers">
|
|
||||||
<set>QAbstractItemView::NoEditTriggers</set>
|
|
||||||
</property>
|
|
||||||
<property name="verticalScrollMode">
|
|
||||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
|
||||||
</property>
|
|
||||||
<property name="horizontalScrollMode">
|
|
||||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
|
@ -58,6 +45,26 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="ToolComboBox">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Normal Tool</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Spray Can</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer">
|
<spacer name="horizontalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -73,10 +80,23 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListView" name="ListView">
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="verticalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="ButtonBox">
|
<widget class="QDialogButtonBox" name="ButtonBox">
|
||||||
<property name="standardButtons">
|
<property name="standardButtons">
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Save</set>
|
<set>QDialogButtonBox::Close|QDialogButtonBox::Save</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -146,16 +146,26 @@ void CPoiMapModel::RemoveMapping(const QModelIndex& rkIndex, CModelNode *pNode)
|
||||||
{
|
{
|
||||||
QList<CModelNode*> *pList = mModelMap[pPOI];
|
QList<CModelNode*> *pList = mModelMap[pPOI];
|
||||||
pList->removeOne(pNode);
|
pList->removeOne(pNode);
|
||||||
|
mpPoiToWorld->RemovePoiMeshMap(pPOI->Object()->InstanceID(), pNode->FindMeshID());
|
||||||
if (pList->isEmpty())
|
|
||||||
RemovePOI(rkIndex);
|
|
||||||
else
|
|
||||||
mpPoiToWorld->RemovePoiMeshMap(pPOI->Object()->InstanceID(), pNode->FindMeshID());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mpPoiToWorld->RemovePoiMeshMap(pPOI->Object()->InstanceID(), pNode->FindMeshID());
|
mpPoiToWorld->RemovePoiMeshMap(pPOI->Object()->InstanceID(), pNode->FindMeshID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CPoiMapModel::IsModelMapped(const QModelIndex& rkIndex, CModelNode *pNode) const
|
||||||
|
{
|
||||||
|
if (!pNode) return false;
|
||||||
|
|
||||||
|
CScriptNode *pPOI = PoiNodePointer(rkIndex);
|
||||||
|
|
||||||
|
if (mModelMap.contains(pPOI))
|
||||||
|
{
|
||||||
|
QList<CModelNode*> *pList = mModelMap[pPOI];
|
||||||
|
return (pList->contains(pNode));
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
CScriptNode* CPoiMapModel::PoiNodePointer(const QModelIndex& rkIndex) const
|
CScriptNode* CPoiMapModel::PoiNodePointer(const QModelIndex& rkIndex) const
|
||||||
{
|
{
|
||||||
if ((u32) rkIndex.row() < mpPoiToWorld->NumMappedPOIs())
|
if ((u32) rkIndex.row() < mpPoiToWorld->NumMappedPOIs())
|
||||||
|
|
|
@ -31,6 +31,7 @@ public:
|
||||||
void AddMapping(const QModelIndex& rkIndex, CModelNode *pNode);
|
void AddMapping(const QModelIndex& rkIndex, CModelNode *pNode);
|
||||||
void RemovePOI(const QModelIndex& rkIndex);
|
void RemovePOI(const QModelIndex& rkIndex);
|
||||||
void RemoveMapping(const QModelIndex& rkIndex, CModelNode *pNode);
|
void RemoveMapping(const QModelIndex& rkIndex, CModelNode *pNode);
|
||||||
|
bool IsModelMapped(const QModelIndex& rkIndex, CModelNode *pNode) const;
|
||||||
|
|
||||||
CScriptNode* PoiNodePointer(const QModelIndex& rkIndex) const;
|
CScriptNode* PoiNodePointer(const QModelIndex& rkIndex) const;
|
||||||
const QList<CModelNode*>& GetPoiMeshList(const QModelIndex& rkIndex) const;
|
const QList<CModelNode*>& GetPoiMeshList(const QModelIndex& rkIndex) const;
|
||||||
|
|
|
@ -68,7 +68,11 @@ CWorldEditor::CWorldEditor(QWidget *parent) :
|
||||||
addAction(ui->ActionDecrementGizmo);
|
addAction(ui->ActionDecrementGizmo);
|
||||||
|
|
||||||
// Connect signals and slots
|
// Connect signals and slots
|
||||||
connect(ui->MainViewport, SIGNAL(ViewportClick(CSceneNode*,QMouseEvent*)), this, SLOT(OnViewportClick(CSceneNode*,QMouseEvent*)));
|
connect(ui->MainViewport, SIGNAL(ViewportClick(SRayIntersection,QMouseEvent*)), this, SLOT(OnViewportClick(SRayIntersection,QMouseEvent*)));
|
||||||
|
connect(ui->MainViewport, SIGNAL(InputProcessed(SRayIntersection,QMouseEvent*)), this, SLOT(OnViewportInputProcessed(SRayIntersection,QMouseEvent*)));
|
||||||
|
connect(ui->MainViewport, SIGNAL(InputProcessed(SRayIntersection,QMouseEvent*)), this, SLOT(UpdateGizmoUI()) );
|
||||||
|
connect(ui->MainViewport, SIGNAL(InputProcessed(SRayIntersection,QMouseEvent*)), this, SLOT(UpdateStatusBar()) );
|
||||||
|
connect(ui->MainViewport, SIGNAL(InputProcessed(SRayIntersection,QMouseEvent*)), this, SLOT(UpdateCursor()) );
|
||||||
connect(ui->MainViewport, SIGNAL(GizmoMoved()), this, SLOT(OnGizmoMoved()));
|
connect(ui->MainViewport, SIGNAL(GizmoMoved()), this, SLOT(OnGizmoMoved()));
|
||||||
connect(ui->MainViewport, SIGNAL(CameraOrbit()), this, SLOT(UpdateCameraOrbit()));
|
connect(ui->MainViewport, SIGNAL(CameraOrbit()), this, SLOT(UpdateCameraOrbit()));
|
||||||
connect(this, SIGNAL(SelectionModified()), this, SLOT(UpdateCameraOrbit()));
|
connect(this, SIGNAL(SelectionModified()), this, SLOT(UpdateCameraOrbit()));
|
||||||
|
@ -166,7 +170,7 @@ CGameArea* CWorldEditor::ActiveArea()
|
||||||
return mpArea;
|
return mpArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ UPDATE UI ************
|
// ************ PROTECTED SLOTS ************
|
||||||
void CWorldEditor::UpdateStatusBar()
|
void CWorldEditor::UpdateStatusBar()
|
||||||
{
|
{
|
||||||
// Would be cool to do more frequent status bar updates with more info. Unfortunately, this causes lag.
|
// Would be cool to do more frequent status bar updates with more info. Unfortunately, this causes lag.
|
||||||
|
@ -262,13 +266,6 @@ void CWorldEditor::UpdateSelectionUI()
|
||||||
UpdateGizmoUI();
|
UpdateGizmoUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ PROTECTED ************
|
|
||||||
void CWorldEditor::GizmoModeChanged(CGizmo::EGizmoMode mode)
|
|
||||||
{
|
|
||||||
ui->TransformSpinBox->SetSingleStep( (mode == CGizmo::eRotate ? 1.0 : 0.1) );
|
|
||||||
ui->TransformSpinBox->SetDefaultValue( (mode == CGizmo::eScale ? 1.0 : 0.0) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::UpdateCursor()
|
void CWorldEditor::UpdateCursor()
|
||||||
{
|
{
|
||||||
if (ui->MainViewport->IsCursorVisible() && !mPickMode)
|
if (ui->MainViewport->IsCursorVisible() && !mPickMode)
|
||||||
|
@ -284,6 +281,13 @@ void CWorldEditor::UpdateCursor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ************ PROTECTED ************
|
||||||
|
void CWorldEditor::GizmoModeChanged(CGizmo::EGizmoMode mode)
|
||||||
|
{
|
||||||
|
ui->TransformSpinBox->SetSingleStep( (mode == CGizmo::eRotate ? 1.0 : 0.1) );
|
||||||
|
ui->TransformSpinBox->SetDefaultValue( (mode == CGizmo::eScale ? 1.0 : 0.0) );
|
||||||
|
}
|
||||||
|
|
||||||
// ************ PRIVATE SLOTS ************
|
// ************ PRIVATE SLOTS ************
|
||||||
void CWorldEditor::OnPickModeEnter(QCursor Cursor)
|
void CWorldEditor::OnPickModeEnter(QCursor Cursor)
|
||||||
{
|
{
|
||||||
|
@ -300,11 +304,8 @@ void CWorldEditor::RefreshViewport()
|
||||||
if (!mGizmo.IsTransforming())
|
if (!mGizmo.IsTransforming())
|
||||||
mGizmo.ResetSelectedAxes();
|
mGizmo.ResetSelectedAxes();
|
||||||
|
|
||||||
// Process input + update UI
|
// Process input
|
||||||
ui->MainViewport->ProcessInput();
|
ui->MainViewport->ProcessInput();
|
||||||
UpdateCursor();
|
|
||||||
UpdateStatusBar();
|
|
||||||
UpdateGizmoUI();
|
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
ui->MainViewport->Render();
|
ui->MainViewport->Render();
|
||||||
|
|
|
@ -45,16 +45,14 @@ public:
|
||||||
void SetArea(CWorld *pWorld, CGameArea *pArea);
|
void SetArea(CWorld *pWorld, CGameArea *pArea);
|
||||||
CGameArea* ActiveArea();
|
CGameArea* ActiveArea();
|
||||||
|
|
||||||
// Update UI
|
|
||||||
void UpdateStatusBar();
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void UpdateStatusBar();
|
||||||
void UpdateGizmoUI();
|
void UpdateGizmoUI();
|
||||||
void UpdateSelectionUI();
|
void UpdateSelectionUI();
|
||||||
|
void UpdateCursor();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void GizmoModeChanged(CGizmo::EGizmoMode mode);
|
void GizmoModeChanged(CGizmo::EGizmoMode mode);
|
||||||
void UpdateCursor();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void OnPickModeEnter(QCursor Cursor);
|
void OnPickModeEnter(QCursor Cursor);
|
||||||
|
|
Loading…
Reference in New Issue