mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-07-29 08:25:42 +00:00
125 lines
3.4 KiB
C++
125 lines
3.4 KiB
C++
#ifndef CNODESELECTION_H
|
|
#define CNODESELECTION_H
|
|
|
|
#include <Core/Scene/CSceneIterator.h>
|
|
#include <Core/Scene/CSceneNode.h>
|
|
#include <Core/Scene/CScriptNode.h>
|
|
#include <QList>
|
|
#include <QObject>
|
|
|
|
class CNodeSelection : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
FNodeFlags mAllowedNodes{ENodeType::All};
|
|
QList<CSceneNode*> mSelectedNodes;
|
|
|
|
mutable CAABox mCachedBounds;
|
|
mutable bool mBoundsDirty = true;
|
|
|
|
public:
|
|
CNodeSelection() = default;
|
|
|
|
~CNodeSelection() override
|
|
{
|
|
for (CSceneNode *pNode : mSelectedNodes)
|
|
pNode->SetSelected(false);
|
|
}
|
|
|
|
void SelectNode(CSceneNode *pNode)
|
|
{
|
|
if (IsAllowedType(pNode->NodeType()) && !pNode->IsSelected())
|
|
{
|
|
pNode->SetSelected(true);
|
|
mSelectedNodes << pNode;
|
|
mCachedBounds.ExpandBounds(pNode->AABox());
|
|
emit Modified();
|
|
}
|
|
}
|
|
|
|
void DeselectNode(CSceneNode *pNode)
|
|
{
|
|
if (pNode->IsSelected())
|
|
{
|
|
pNode->SetSelected(false);
|
|
mSelectedNodes.removeOne(pNode);
|
|
mBoundsDirty = true;
|
|
emit Modified();
|
|
}
|
|
}
|
|
|
|
void Clear()
|
|
{
|
|
for (CSceneNode *pNode : mSelectedNodes)
|
|
pNode->SetSelected(false);
|
|
|
|
mSelectedNodes.clear();
|
|
mBoundsDirty = true;
|
|
emit Modified();
|
|
}
|
|
|
|
void ClearAndSelectNode(CSceneNode *pNode)
|
|
{
|
|
// Block signals for Clear so that Modified only emits once.
|
|
blockSignals(true);
|
|
Clear();
|
|
blockSignals(false);
|
|
SelectNode(pNode);
|
|
}
|
|
|
|
void SetSelectedNodes(const QList<CSceneNode*>& rkList)
|
|
{
|
|
blockSignals(true);
|
|
Clear();
|
|
|
|
for (CSceneNode *pNode : rkList)
|
|
SelectNode(pNode);
|
|
blockSignals(false);
|
|
|
|
mBoundsDirty = true;
|
|
emit Modified();
|
|
}
|
|
|
|
CAABox Bounds() const
|
|
{
|
|
if (mBoundsDirty)
|
|
{
|
|
mCachedBounds = CAABox::Infinite();
|
|
|
|
for (CSceneNode *pNode : mSelectedNodes)
|
|
{
|
|
mCachedBounds.ExpandBounds(pNode->AABox());
|
|
|
|
if (pNode->NodeType() == ENodeType::Script)
|
|
{
|
|
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
|
|
|
|
if (pScript->HasPreviewVolume())
|
|
mCachedBounds.ExpandBounds(pScript->PreviewVolumeAABox());
|
|
}
|
|
}
|
|
|
|
mBoundsDirty = false;
|
|
}
|
|
|
|
return mCachedBounds;
|
|
}
|
|
|
|
uint32 Size() const { return mSelectedNodes.size(); }
|
|
bool IsEmpty() const { return Size() == 0; }
|
|
CSceneNode* At(uint32 Index) const { return mSelectedNodes[Index]; }
|
|
CSceneNode* Front() const { return mSelectedNodes.front(); }
|
|
CSceneNode* Back() const { return mSelectedNodes.back(); }
|
|
CSceneNode* operator[](uint32 Index) const { return mSelectedNodes[Index]; }
|
|
void UpdateBounds() { mBoundsDirty = true; }
|
|
void SetAllowedNodeTypes(FNodeFlags Types) { mAllowedNodes = Types; }
|
|
bool IsAllowedType(ENodeType Type) const { return (mAllowedNodes & Type) != 0; }
|
|
bool IsAllowedType(CSceneNode *pNode) const { return (mAllowedNodes & pNode->NodeType()) != 0; }
|
|
QList<CSceneNode*> SelectedNodeList() const { return mSelectedNodes; }
|
|
|
|
signals:
|
|
void Modified();
|
|
};
|
|
|
|
#endif // CNODESELECTION_H
|