/
Group.h
182 lines (145 loc) · 4.51 KB
/
Group.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#pragma once
#include "i18n.h"
#include "imap.h"
#include "iundo.h"
#include "iselection.h"
#include "iselectiongroup.h"
#include "iscenegraph.h"
#include "selectionlib.h"
#include "SelectableNode.h"
#include "command/ExecutionNotPossible.h"
namespace selection
{
namespace detail
{
inline ISelectionGroupManager& getMapSelectionGroupManager()
{
assert(GlobalMapModule().getRoot());
return GlobalMapModule().getRoot()->getSelectionGroupManager();
}
}
/**
* Returns if the groupSelected command is able to execute
* at this point, otherwise throws cmd::ExecutionNotPossible
*/
inline void checkGroupSelectedAvailable()
{
if (!GlobalMapModule().getRoot())
{
throw cmd::ExecutionNotPossible(_("No map loaded"));
}
if (GlobalSelectionSystem().getSelectionMode() != SelectionMode::Primitive &&
GlobalSelectionSystem().getSelectionMode() != SelectionMode::GroupPart)
{
throw cmd::ExecutionNotPossible(_("Groups can be formed in Primitive and Group Part selection mode only"));
}
if (GlobalSelectionSystem().getSelectionInfo().totalCount == 0)
{
throw cmd::ExecutionNotPossible(_("Nothing selected, cannot group anything"));
}
if (GlobalSelectionSystem().getSelectionInfo().totalCount == 1)
{
throw cmd::ExecutionNotPossible(_("Select more than one element to form a group"));
return;
}
// Check if the current selection already is member of the same group
std::set<std::size_t> groupIds;
bool hasUngroupedNode = false;
GlobalSelectionSystem().foreachSelected([&](const scene::INodePtr& node)
{
std::shared_ptr<IGroupSelectable> selectable = std::dynamic_pointer_cast<IGroupSelectable>(node);
if (!selectable) return;
if (!selectable->getGroupIds().empty())
{
groupIds.insert(selectable->getMostRecentGroupId());
}
else
{
hasUngroupedNode = true;
}
});
if (!hasUngroupedNode && groupIds.size() == 1)
{
throw cmd::ExecutionNotPossible(_("The selected elements already form a group"));
}
}
/**
* Groups the currently selected elements.
* Will throw cmd::ExecutionNotPossible if it cannot execute.
*/
inline void groupSelected()
{
// This will throw exceptions
checkGroupSelectedAvailable();
UndoableCommand cmd("GroupSelected");
ISelectionGroupPtr group = detail::getMapSelectionGroupManager().createSelectionGroup();
GlobalSelectionSystem().foreachSelected([&](const scene::INodePtr& node)
{
group->addNode(node);
});
SceneChangeNotify();
}
/**
* Returns if the ungroupSelected command is able to execute
* at this point, otherwise throws cmd::ExecutionNotPossible.
*/
inline void checkUngroupSelectedAvailable()
{
if (!GlobalMapModule().getRoot())
{
throw cmd::ExecutionNotPossible(_("No map loaded"));
}
if (GlobalSelectionSystem().getSelectionMode() != SelectionMode::Primitive &&
GlobalSelectionSystem().getSelectionMode() != SelectionMode::GroupPart)
{
throw cmd::ExecutionNotPossible(_("Groups can be dissolved in Primitive and Group Part selection mode only"));
}
if (GlobalSelectionSystem().getSelectionInfo().totalCount == 0)
{
throw cmd::ExecutionNotPossible(_("Nothing selected, cannot un-group anything"));
}
// Check if the current selection already is member of the same group
bool hasOnlyUngroupedNodes = true;
GlobalSelectionSystem().foreachSelected([&](const scene::INodePtr& node)
{
std::shared_ptr<IGroupSelectable> selectable = std::dynamic_pointer_cast<IGroupSelectable>(node);
if (!selectable) return;
if (!selectable->getGroupIds().empty())
{
hasOnlyUngroupedNodes = false;
}
});
if (hasOnlyUngroupedNodes)
{
throw cmd::ExecutionNotPossible(_("The selected elements aren't part of any group"));
}
}
/**
* Resolve the currently selected group.
* Will throw cmd::ExecutionNotPossible if it cannot execute.
*/
inline void ungroupSelected()
{
// Will throw exceptions if not available
checkUngroupSelectedAvailable();
UndoableCommand cmd("UngroupSelected");
// Collect all the latest group Ids from all selected nodes
std::set<std::size_t> ids;
GlobalSelectionSystem().foreachSelected([&](const scene::INodePtr& node)
{
std::shared_ptr<scene::SelectableNode> selectable = std::dynamic_pointer_cast<scene::SelectableNode>(node);
if (!selectable) return;
if (selectable->isGroupMember())
{
ids.insert(selectable->getMostRecentGroupId());
}
});
auto& selGroupMgr = detail::getMapSelectionGroupManager();
// Now remove the found group by ID (maybe convert them to a selection set before removal?)
std::for_each(ids.begin(), ids.end(), [&](std::size_t id)
{
selGroupMgr.deleteSelectionGroup(id);
});
SceneChangeNotify();
}
}