Radium Engine  1.5.20
Loading...
Searching...
No Matches
EntityTreeModel.cpp
1#include <Gui/TreeModel/EntityTreeModel.hpp>
2
3#include <stack>
4
5#include <Engine/Scene/Component.hpp>
6#include <Engine/Scene/Entity.hpp>
7
8#include <Engine/Rendering/RenderObject.hpp>
9#include <Engine/Rendering/RenderObjectManager.hpp>
10#include <Engine/Scene/EntityManager.hpp>
11
13
14namespace Ra {
15namespace Gui {
16
18 m_rootItem.reset( new EngineTreeItem );
19 m_rootItem->m_parent = nullptr;
20
21 auto roManager = m_engine->getRenderObjectManager();
22 for ( const auto& ent : m_engine->getEntityManager()->getEntities() ) {
23 EngineTreeItem* entityItem = new EngineTreeItem;
24 entityItem->m_entry = ItemEntry( ent );
25 entityItem->m_parent = m_rootItem.get();
26 for ( const auto& comp : ent->getComponents() ) {
27 if ( comp ) {
28 EngineTreeItem* componentItem = new EngineTreeItem;
29 componentItem->m_entry = ItemEntry( ent, comp.get() );
30 componentItem->m_parent = entityItem;
31 for ( const auto& roIdx : comp->m_renderObjects ) {
32 EngineTreeItem* roItem = new EngineTreeItem;
33 roItem->m_entry = ItemEntry( ent, comp.get(), roIdx );
34 roItem->m_parent = componentItem;
35 roItem->setChecked( roManager->getRenderObject( roIdx )->isVisible() );
36 componentItem->m_children.emplace_back( roItem );
37 }
38 entityItem->m_children.emplace_back( componentItem );
39 }
40 }
41 m_rootItem->m_children.emplace_back( entityItem );
42 }
43}
44
45const ItemEntry& ItemModel::getEntry( const QModelIndex& index ) const {
46 return static_cast<EngineTreeItem*>( getItem( index ) )->m_entry;
47}
48
49QModelIndex ItemModel::findEntryIndex( const ItemEntry& entry ) const {
50 if ( entry.isValid() ) {
52 stack.push( m_rootItem.get() );
53 while ( !stack.empty() ) {
54 EngineTreeItem* item = static_cast<EngineTreeItem*>( stack.top() );
55 stack.pop();
56 // Found item, so build the index corresponding to it.
57 if ( item->m_entry == entry ) {
58 return createIndex( item->getIndexInParent(), 0, item );
59 }
60
61 // Add children to the stack
62 for ( const auto& child : item->m_children ) {
63 stack.push( child.get() );
64 }
65 }
66 }
67
68 return QModelIndex();
69}
70
71void ItemModel::addItem( const Engine::Scene::ItemEntry& ent ) {
72 CORE_ASSERT( ent.isValid(), "Inserting invalid entry" );
73 CORE_ASSERT( !findEntryIndex( ent ).isValid(), "Entry already in model" );
74 auto roManager = m_engine->getRenderObjectManager();
75
76 if ( !findEntryIndex( ent ).isValid() ) {
77 TreeItem* parentItem;
78 QModelIndex parentIdx;
79 if ( ent.isEntityNode() ) { parentItem = m_rootItem.get(); }
80 else {
81 ItemEntry parentEntry;
82 if ( ent.isRoNode() ) { parentEntry = ItemEntry( ent.m_entity, ent.m_component ); }
83 else if ( ent.isComponentNode() ) { parentEntry = ItemEntry( ent.m_entity ); }
84 parentIdx = findEntryIndex( parentEntry );
85 CORE_ASSERT( parentIdx.isValid(), "Parent does not exist" );
86 parentItem = getItem( parentIdx );
87 }
88
89 CORE_ASSERT( getItem( parentIdx ) == parentItem, "Model inconsistency" );
90
91 EngineTreeItem* childItem = new EngineTreeItem;
92 childItem->m_entry = ent;
93 childItem->m_parent = parentItem;
94 if ( ent.isRoNode() ) {
95 childItem->setChecked( roManager->getRenderObject( ent.m_roIndex )->isVisible() );
96 // update parent checkbox if every ro aren't visible
97 bool checked = roManager->getRenderObject( ent.m_roIndex )->isVisible();
98 auto pent = static_cast<EngineTreeItem*>( parentItem )->m_entry.m_component;
99 for ( const auto& roIdx : pent->getRenderObjects() ) {
100 checked = checked || roManager->getRenderObject( roIdx )->isVisible();
101 }
102
103 parentItem->setChecked( checked );
104 }
105 else if ( ent.isComponentNode() ) {
106 //
107 bool checked = false;
108 for ( const auto& roIdx : ent.m_component->getRenderObjects() ) {
109 checked = checked || roManager->getRenderObject( roIdx )->isVisible();
110 }
111 childItem->setChecked( checked );
112 }
113
114 int row = int( parentItem->m_children.size() );
115 beginInsertRows( parentIdx, row, row );
116 parentItem->m_children.emplace_back( childItem );
117 endInsertRows();
118 }
119}
120
121void ItemModel::removeItem( const Engine::Scene::ItemEntry& ent ) {
122 QModelIndex entryIndex = findEntryIndex( ent );
123 CORE_ASSERT( ent.isValid(), "Removing invalid entry" );
124 CORE_ASSERT( entryIndex.isValid(), "Entry not in model" );
125 if ( entryIndex.isValid() ) {
126 EngineTreeItem* toRemove = static_cast<EngineTreeItem*>( getItem( entryIndex ) );
127 TreeItem* parentItem = toRemove->m_parent;
128 auto& childList = parentItem->m_children;
129 const auto childPos =
130 std::find_if( childList.begin(), childList.end(), [toRemove]( const auto& ptr ) {
131 return ptr.get() == toRemove;
132 } );
133
134 CORE_ASSERT( childPos != childList.end(), "Child not in parent's list" );
135 int row = toRemove->getIndexInParent();
136 CORE_ASSERT( childPos - childList.begin() == row, "Iterator consistency error" );
137 beginRemoveRows( parent( entryIndex ), row, row );
138 parentItem->m_children.erase( childPos );
139 endRemoveRows();
140 }
141}
142
143void ItemModel::onDataChanged( const QModelIndex& topLeft,
144 const QModelIndex& bottomRight,
145 const QVector<int>& roles ) {
146 if ( topLeft == bottomRight && roles.size() == 1 && roles.first() == Qt::CheckStateRole ) {
147 auto index = topLeft;
148 if ( index.isValid() ) {
149 bool visible = getItem( index )->isChecked();
150 auto ent = getEntry( index );
151
152 if ( ent.isValid() && ent.isRoNode() ) {
153 emit visibilityROChanged( ent.m_roIndex, visible );
154 }
155 }
156 }
157}
158
160 CORE_ASSERT( m_parent, "Looking for the root item's index." );
161 for ( uint i = 0; i < m_parent->m_children.size(); ++i ) {
162 if ( m_parent->m_children[i].get() == this ) { return i; }
163 }
164 // If we reached here, it means that the item
165 // was not found in its parent's child list.
166 // indicating the tree is corrupted.
167 CORE_ASSERT( false, " Did not find child in parent" );
168 return -1;
169}
170
171} // namespace Gui
172} // namespace Ra
Scene::EntityManager * getEntityManager() const
Rendering::RenderObjectManager * getRenderObjectManager() const
Manager getters.
void buildModel() override
Internal function to build the tree.
QModelIndex findEntryIndex(const Engine::Scene::ItemEntry &entry) const
const Engine::Scene::ItemEntry & getEntry(const QModelIndex &index) const
const Engine::RadiumEngine * m_engine
Engine instance.
Base class for element of the tree representation.
Definition TreeModel.hpp:31
int getIndexInParent() const
std::vector< std::unique_ptr< TreeItem > > m_children
Children of item in the tree.
Definition TreeModel.hpp:70
TreeItem * getItem(const QModelIndex &index) const
Get the tree item corresponding to the given index.
Definition TreeModel.cpp:20
QModelIndex parent(const QModelIndex &child) const override
Definition TreeModel.cpp:75
std::unique_ptr< TreeItem > m_rootItem
Root of the tree.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition TreeModel.cpp:63
T empty(T... args)
T find_if(T... args)
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:3
T pop(T... args)
T push(T... args)
Ra::Core::Utils::Index m_roIndex
RO index of the represented object.
Definition ItemEntry.hpp:67
bool isValid() const
Returns true if the item represents any valid object.
Definition ItemEntry.cpp:42
bool isComponentNode() const
Returns true if the item represents a component.
Definition ItemEntry.hpp:85
Entity * m_entity
The entity represented by the item, or owning the object represented.
Definition ItemEntry.hpp:60
bool isEntityNode() const
Returns true if the item represents an entity.
Definition ItemEntry.hpp:80
bool isRoNode() const
Returns true if the item represents a render object.
Definition ItemEntry.hpp:90
T top(T... args)