!XT (BREAK-16) (Sandbox) Remove double-newlines at the end of files.
[CRYENGINE.git] / Code / Sandbox / Plugins / EditorParticle / Models / ParticleGraphItems.cpp
blob6a6f9d5e4495edf9c20d8b85845678da4eaa78d6
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
3 #include "StdAfx.h"
4 #include "ParticleGraphItems.h"
6 #include "../Undo.h"
8 #include "Widgets/FeatureGridNodeContentWidget.h"
9 #include "Widgets/NodeIcons.h"
11 #include "ParticleGraphModel.h"
13 #include "QtUtil.h"
15 #include <NodeGraph/NodeWidget.h>
16 #include <NodeGraph/PinWidget.h>
17 #include <NodeGraph/ConnectionWidget.h>
18 #include <NodeGraph/NodeGraphViewStyle.h>
20 #include <QVariant>
22 namespace CryParticleEditor {
24 CNodeItem::CNodeItem(pfx2::IParticleComponent& component, CryGraphEditor::CNodeGraphViewModel& viewModel)
25 : CAbstractNodeItem(*(m_pData = new CryGraphEditor::CNodeEditorData()), viewModel)
26 , m_component(component)
28 SetAcceptsDeactivation(true);
29 SetAcceptsRenaming(true);
31 m_name = component.GetName();
32 m_data.SetPos(Vec2(component.GetNodePosition().x, component.GetNodePosition().y));
34 uint32 featureCount = m_component.GetNumFeatures();
35 m_pins.reserve(featureCount + 1);
37 m_pins.push_back(new CParentPinItem(*this));
38 m_pins.push_back(new CChildPinItem(*this));
40 for (uint32 i = 0; i < featureCount; ++i)
42 pfx2::IParticleFeature* pFeature = m_component.GetFeature(i);
43 if (pFeature)
45 CFeatureItem* pFeatureItem = new CFeatureItem(*pFeature, *this, viewModel);
46 m_features.push_back(pFeatureItem);
47 if (pFeatureItem->HasComponentConnector())
49 m_pins.push_back(pFeatureItem->GetPinItem());
55 CNodeItem::~CNodeItem()
57 for (CryGraphEditor::CAbstractPinItem* pItem : m_pins)
59 CBasePinItem* pPintItem = static_cast<CBasePinItem*>(pItem);
60 if (pPintItem->GetPinType() == EPinType::Parent || pPintItem->GetPinType() == EPinType::Child)
61 delete pPintItem;
64 for (CFeatureItem* pItem : m_features)
66 delete pItem;
69 delete m_pData;
72 void CNodeItem::SetPosition(QPointF position)
74 m_component.SetNodePosition(Vec2(position.x(), position.y()));
75 CAbstractNodeItem::SetPosition(position);
76 if (GetIEditor()->GetIUndoManager()->IsUndoRecording())
78 CryGraphEditor::CUndoNodeMove* pUndoObject = new CryGraphEditor::CUndoNodeMove(*this);
79 CUndo::Record(pUndoObject);
83 CryGraphEditor::CNodeWidget* CNodeItem::CreateWidget(CryGraphEditor::CNodeGraphView& view)
85 CryGraphEditor::CNodeWidget* pNode = new CryGraphEditor::CNodeWidget(*this, view);
86 pNode->SetHeaderNameWidth(120);
87 CFeatureGridNodeContentWidget* pContent = new CFeatureGridNodeContentWidget(*pNode, static_cast<CParentPinItem&>(*m_pins[0]), static_cast<CChildPinItem&>(*m_pins[1]), view);
89 pNode->AddHeaderIcon(new CEmitterActiveIcon(*pNode), CryGraphEditor::CHeaderWidget::EIconSlot::Right);
90 pNode->AddHeaderIcon(new CEmitterVisibleIcon(*pNode), CryGraphEditor::CHeaderWidget::EIconSlot::Right);
91 pNode->AddHeaderIcon(new CSoloEmitterModeIcon(*pNode), CryGraphEditor::CHeaderWidget::EIconSlot::Right);
93 pNode->SetContentWidget(pContent);
95 return pNode;
98 QVariant CNodeItem::GetId() const
100 return QVariant::fromValue(QString(m_component.GetName()));
103 bool CNodeItem::HasId(QVariant id) const
105 QString nodeName = m_component.GetName();
106 return (nodeName == id.value<QString>());
109 QVariant CNodeItem::GetTypeId() const
111 // Note: Nodes in particle system don't have a type yet.
112 return QVariant::fromValue(QString());
115 QString CNodeItem::GetName() const
117 return QString(m_component.GetName());
120 void CNodeItem::SetName(const QString& name)
122 const string newName = QtUtil::ToString(name);
123 const string oldName = m_component.GetName();
124 if (oldName != newName)
126 m_component.SetName(newName.c_str());
127 CAbstractNodeItem::SetName(GetName());
129 // TODO: Move this into an CAbstractNodeItem method.
130 if (GetIEditor()->GetIUndoManager()->IsUndoRecording())
132 CUndo::Record(new CryGraphEditor::CUndoNodeNameChange(*this, oldName.c_str()));
134 // ~TODO
138 bool CNodeItem::IsDeactivated() const
140 return !m_component.IsEnabled();
143 void CNodeItem::SetDeactivated(bool isDeactivated)
145 if (IsDeactivated() != isDeactivated)
147 m_component.SetEnabled(!isDeactivated);
148 SignalDeactivatedChanged(isDeactivated);
149 static_cast<CParticleGraphModel*>(&GetViewModel())->OnNodeItemChanged(this);
153 void CNodeItem::Serialize(Serialization::IArchive& archive)
155 const string oldName = m_component.GetName();
157 m_component.Serialize(archive);
159 // Note: Update everything.
160 const uint32 numFeatures = m_component.GetNumFeatures();
161 FeatureItemArray features;
162 features.reserve(numFeatures);
163 CryGraphEditor::PinItemArray pins;
164 pins.push_back(m_pins[0]);
165 pins.push_back(m_pins[1]);
167 size_t movedFeatures = 0;
169 for (uint32 i = 0; i < numFeatures; ++i)
171 pfx2::IParticleFeature* pFeatureInterface = m_component.GetFeature(i);
172 auto predicate = [pFeatureInterface](CFeatureItem* pFeatureItem) -> bool
174 return (pFeatureItem && pFeatureInterface == &pFeatureItem->GetFeatureInterface());
177 auto result = std::find_if(m_features.begin(), m_features.end(), predicate);
178 if (result == m_features.end())
180 CFeatureItem* pFeatureItem = new CFeatureItem(*pFeatureInterface, *this, GetViewModel());
181 features.push_back(pFeatureItem);
182 if (pFeatureItem->HasComponentConnector())
184 pins.push_back(pFeatureItem->GetPinItem());
187 SignalFeatureAdded(*pFeatureItem);
189 else
191 CFeatureItem* pFeatureItem = *result;
192 features.push_back(pFeatureItem);
193 if (pFeatureItem->HasComponentConnector())
195 pins.push_back(pFeatureItem->GetPinItem());
198 pFeatureItem->SignalInvalidated();
199 *result = nullptr;
200 ++movedFeatures;
204 for (size_t i = 0; i < m_features.size(); ++i)
206 if (m_features[i] != nullptr)
207 RemoveFeature(i);
210 CRY_ASSERT(m_features.size() == movedFeatures);
212 m_features.swap(features);
213 m_pins.swap(pins);
215 CRY_ASSERT(m_features.size() == numFeatures);
217 SignalInvalidated();
220 CParentPinItem* CNodeItem::GetParentPinItem()
222 return static_cast<CParentPinItem*>(m_pins[0]);
225 CChildPinItem* CNodeItem::GetChildPinItem()
227 return static_cast<CChildPinItem*>(m_pins[1]);
230 uint32 CNodeItem::GetIndex() const
232 CParticleGraphModel& model = static_cast<CParticleGraphModel&>(GetViewModel());
233 const pfx2::IParticleEffectPfx2& effect = model.GetEffectInterface();
235 const uint32 numNodes = effect.GetNumComponents();
236 for (uint32 i = 0; i < numNodes; ++i)
238 if (effect.GetComponent(i) == &m_component)
239 return i;
242 return ~0;
245 CFeatureItem* CNodeItem::AddFeature(uint32 index, const pfx2::SParticleFeatureParams& featureParams)
247 m_component.AddFeature(index, featureParams);
249 pfx2::IParticleFeature* pFeature = m_component.GetFeature(index);
250 if (pFeature)
252 CFeatureItem* pFeatureItem = new CFeatureItem(*pFeature, *this, GetViewModel());
253 m_features.insert(m_features.begin() + index, pFeatureItem);
254 if (pFeatureItem->HasComponentConnector())
256 m_pins.push_back(pFeatureItem->GetPinItem());
258 SignalFeatureAdded(*pFeatureItem);
260 if (GetIEditor()->GetIUndoManager()->IsUndoRecording())
262 CUndo::Record(new CUndoFeatureCreate(*pFeatureItem));
265 return pFeatureItem;
267 return nullptr;
270 void CNodeItem::RemoveFeature(uint32 index)
272 if (m_features.size() > index)
274 CFeatureItem* pFeatureItem = m_features.at(index);
276 GetViewModel().SignalRemoveCustomItem(*pFeatureItem);
277 SignalFeatureRemoved(*pFeatureItem);
279 m_features.erase(m_features.begin() + index);
281 if (CFeaturePinItem* pFeaturePinItem = pFeatureItem->GetPinItem())
283 if (pFeaturePinItem->IsConnected())
285 CParticleGraphModel& model = static_cast<CParticleGraphModel&>(GetViewModel());
286 for (CryGraphEditor::CAbstractConnectionItem* pConnectionItem : pFeaturePinItem->GetConnectionItems())
288 model.RemoveConnection(*pConnectionItem);
291 auto result = std::find(m_pins.begin(), m_pins.end(), pFeatureItem->GetPinItem());
292 CRY_ASSERT(result != m_pins.end());
293 m_pins.erase(result);
296 if (GetIEditor()->GetIUndoManager()->IsUndoRecording())
297 CUndo::Record(new CUndoFeatureRemove(*pFeatureItem));
299 delete pFeatureItem;
302 if (index < m_component.GetNumFeatures())
303 m_component.RemoveFeature(index);
306 bool CNodeItem::MoveFeatureAtIndex(uint32 featureIndex, uint32 destIndex)
308 const uint32 maxIndex = m_features.size() - 1;
309 destIndex = std::min(destIndex, maxIndex);
310 if (featureIndex != destIndex)
312 const size_t numFeatures = m_features.size();
313 std::vector<uint32> ids;
314 ids.reserve(m_features.size());
316 for (size_t i = 0; i < numFeatures; ++i)
317 ids.push_back(i);
319 CFeatureItem* pFeatureItem = m_features[featureIndex];
321 ids.erase(ids.begin() + featureIndex);
322 ids.insert(ids.begin() + destIndex, featureIndex);
324 m_component.SwapFeatures(&ids[0], ids.size());
326 m_features.erase(m_features.begin() + featureIndex);
327 m_features.insert(m_features.begin() + destIndex, pFeatureItem);
329 if (m_component.GetFeature(destIndex) == &pFeatureItem->GetFeatureInterface())
331 SignalFeatureMoved(*pFeatureItem);
332 if (GetIEditor()->GetIUndoManager()->IsUndoRecording())
334 CUndo::Record(new CUndoFeatureMove(*pFeatureItem, featureIndex));
335 return true;
339 return false;
342 void CNodeItem::SetVisible(bool isVisible)
344 if (isVisible != m_component.IsVisible())
346 m_component.SetVisible(isVisible);
347 SignalVisibleChanged(isVisible);
348 static_cast<CParticleGraphModel*>(&GetViewModel())->OnNodeItemChanged(this);
352 bool CNodeItem::IsVisible()
354 return m_component.IsVisible();
357 CFeaturePinItem::CFeaturePinItem(CFeatureItem& feature)
358 : CBasePinItem(feature.GetNodeItem())
359 , m_featureItem(feature)
363 QString CFeaturePinItem::GetName() const
365 return m_featureItem.GetName();
368 QVariant CFeaturePinItem::GetId() const
370 return QVariant::fromValue(m_featureItem.GetName());
373 bool CFeaturePinItem::HasId(QVariant id) const
375 return (m_featureItem.GetName() == id.value<QString>());
378 bool CFeaturePinItem::CanConnect(const CryGraphEditor::CAbstractPinItem* pOtherPin) const
380 if (pOtherPin)
381 return pOtherPin->IsInputPin() && !pOtherPin->IsConnected();
383 return true;
386 CFeatureItem::CFeatureItem(pfx2::IParticleFeature& feature, CNodeItem& node, CryGraphEditor::CNodeGraphViewModel& viewModel)
387 : CAbstractNodeGraphViewModelItem(viewModel)
388 , m_featureInterface(feature)
389 , m_node(node)
391 m_pPin = HasComponentConnector() ? new CFeaturePinItem(*this) : nullptr;
393 SetAcceptsDeactivation(true);
394 SetAcceptsHighlightning(true);
395 SetAcceptsSelection(true);
398 CFeatureItem::~CFeatureItem()
400 delete m_pPin;
403 bool CFeatureItem::IsDeactivated() const
405 return m_featureInterface.IsEnabled() == false;
408 void CFeatureItem::SetDeactivated(bool isDeactivated)
410 if (!m_featureInterface.IsEnabled() != isDeactivated)
412 m_featureInterface.SetEnabled(!isDeactivated);
413 m_node.GetComponentInterface().SetChanged();
414 SignalItemDeactivatedChanged(isDeactivated);
416 // Note: Property tree listens only to node properties changed
417 // events. So at least for now we need to invalidate the whole node.
418 m_node.SignalInvalidated();
419 static_cast<CParticleGraphModel*>(&GetViewModel())->OnNodeItemChanged(&m_node);
423 void CFeatureItem::Serialize(Serialization::IArchive& archive)
425 pfx2::IParticleComponent& component = GetNodeItem().GetComponentInterface();
426 Serialization::SContext context(archive, &component);
427 m_featureInterface.Serialize(archive);
428 if (archive.isInput())
430 component.SetChanged();
431 SignalInvalidated();
435 QString CFeatureItem::GetGroupName() const
437 const pfx2::SParticleFeatureParams& params = m_featureInterface.GetFeatureParams();
438 return QString(params.m_groupName);
441 QString CFeatureItem::GetName() const
443 const pfx2::SParticleFeatureParams& params = m_featureInterface.GetFeatureParams();
444 return QString(params.m_featureName);
447 uint32 CFeatureItem::GetIndex() const
449 pfx2::IParticleComponent& component = m_node.GetComponentInterface();
451 for (uint32 i = 0; i < component.GetNumFeatures(); ++i)
453 if (component.GetFeature(i) == &m_featureInterface)
455 return i;
459 CRY_ASSERT_MESSAGE(0, "Invalid feature item!");
460 return ~0;
463 bool CFeatureItem::HasComponentConnector() const
465 const pfx2::SParticleFeatureParams& params = m_featureInterface.GetFeatureParams();
466 return params.m_hasComponentConnector;
469 QColor CFeatureItem::GetColor() const
471 const pfx2::SParticleFeatureParams& params = m_featureInterface.GetFeatureParams();
472 return QColor(params.m_color.r, params.m_color.g, params.m_color.b);
475 CConnectionItem::CConnectionItem(CBasePinItem& sourcePin, CBasePinItem& targetPin, CryGraphEditor::CNodeGraphViewModel& viewModel)
476 : CryGraphEditor::CAbstractConnectionItem(viewModel)
477 , m_sourcePin(sourcePin)
478 , m_targetPin(targetPin)
480 m_sourcePin.AddConnection(*this);
481 m_targetPin.AddConnection(*this);
483 string sourceNodeName = QtUtil::ToString(m_sourcePin.GetNodeItem().GetName());
484 string sourceNodePin = QtUtil::ToString(m_sourcePin.GetName());
485 string targetNodeName = QtUtil::ToString(m_targetPin.GetNodeItem().GetName());
486 string targetNodePin = QtUtil::ToString(m_targetPin.GetName());
488 string id;
489 id.Format("%s-%s::%s-%s", sourceNodeName, sourceNodePin, targetNodeName, targetNodePin);
491 m_id = CCrc32::Compute(id.c_str());
494 CConnectionItem::~CConnectionItem()
499 CryGraphEditor::CConnectionWidget* CConnectionItem::CreateWidget(CryGraphEditor::CNodeGraphView& view)
501 return new CryGraphEditor::CConnectionWidget(this, view);
504 QVariant CConnectionItem::GetId() const
506 return QVariant::fromValue(m_id);
509 bool CConnectionItem::HasId(QVariant id) const
511 return (GetId().value<uint32>() == id.value<uint32>());
514 void CConnectionItem::OnConnectionRemoved()
516 m_sourcePin.RemoveConnection(*this);
517 m_targetPin.RemoveConnection(*this);