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 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
#pragma once
#include "irenderable.h"
#include "iselection.h"
#include "iselectiontest.h"
#include "icommandsystem.h"
#include "imap.h"
#include "selectionlib.h"
#include "SelectedNodeList.h"
#include "SceneManipulationPivot.h"
namespace selection
{
class RadiantSelectionSystem final :
public SelectionSystem,
public Renderable,
public ISceneSelectionTesterFactory
{
private:
SceneManipulationPivot _pivot;
std::set<Observer*> _observers;
// The 3D volume surrounding the most recent selection.
WorkZone _workZone;
// When this is set to TRUE, the idle callback will emit a scenegraph change call
// This is to avoid massive calls to GlobalSceneGraph().sceneChanged() on each
// and every selection change.
mutable bool _requestWorkZoneRecalculation;
// A simple set that gets filled after the SelectableSortedSet is populated.
// greebo: I used this to merge two SelectionPools (entities and primitives)
// with a preferred sorting (see RadiantSelectionSystem::testSelectScene)
typedef std::list<ISelectable*> SelectablesList;
SelectionInfo _selectionInfo;
sigc::signal<void, const ISelectable&> _sigSelectionChanged;
std::map<std::size_t, ISceneManipulator::Ptr> _manipulators;
// The currently active manipulator
ISceneManipulator::Ptr _activeManipulator;
IManipulator::Type _defaultManipulatorType;
// state
SelectionMode _mode;
ComponentSelectionMode _componentMode;
std::size_t _countPrimitive;
std::size_t _countComponent;
// The internal list to keep track of the selected instances (components and primitives)
SelectedNodeList _selection;
SelectedNodeList _componentSelection;
// The coordinates of the mouse pointer when the manipulation starts
Vector2 _deviceStart;
bool nothingSelected() const;
sigc::signal<void, IManipulator::Type> _sigActiveManipulatorChanged;
sigc::signal<void, SelectionMode> _sigSelectionModeChanged;
sigc::signal<void, ComponentSelectionMode> _sigComponentModeChanged;
bool _selectionFocusActive;
std::set<scene::INodePtr> _selectionFocusPool;
public:
RadiantSelectionSystem();
/** greebo: Returns a structure with all the related
* information about the current selection (brush count,
* entity count, etc.)
*/
const SelectionInfo& getSelectionInfo() override;
void onSceneBoundsChanged();
void pivotChanged() override;
void pivotChangedSelection(const ISelectable& selectable);
void addObserver(Observer* observer) override;
void removeObserver(Observer* observer) override;
void setSelectionMode(SelectionMode mode) override;
SelectionMode getSelectionMode() const override;
void SetComponentMode(ComponentSelectionMode mode) override;
ComponentSelectionMode ComponentMode() const override;
sigc::signal<void, SelectionMode>& signal_selectionModeChanged() override;
sigc::signal<void, ComponentSelectionMode>& signal_componentModeChanged() override;
// Returns the ID of the registered manipulator
std::size_t registerManipulator(const ISceneManipulator::Ptr& manipulator) override;
void unregisterManipulator(const ISceneManipulator::Ptr& manipulator) override;
IManipulator::Type getActiveManipulatorType() override;
const ISceneManipulator::Ptr& getActiveManipulator() override;
void setActiveManipulator(std::size_t manipulatorId) override;
void setActiveManipulator(IManipulator::Type manipulatorType) override;
sigc::signal<void, IManipulator::Type>& signal_activeManipulatorChanged() override;
std::size_t countSelected() const override;
std::size_t countSelectedComponents() const override;
void onSelectedChanged(const scene::INodePtr& node, const ISelectable& selectable) override;
void onComponentSelection(const scene::INodePtr& node, const ISelectable& selectable) override;
SelectionChangedSignal signal_selectionChanged() const override
{
return _sigSelectionChanged;
}
scene::INodePtr ultimateSelected() override;
scene::INodePtr penultimateSelected() override;
void setSelectedAll(bool selected) override;
void setSelectedAllComponents(bool selected) override;
void foreachSelected(const std::function<void(const scene::INodePtr&)>& functor) override;
void foreachSelectedComponent(const Visitor& visitor) override;
void foreachSelectedComponent(const std::function<void(const scene::INodePtr&)>& functor) override;
void foreachBrush(const std::function<void(Brush&)>& functor) override;
void foreachFace(const std::function<void(IFace&)>& functor) override;
void foreachPatch(const std::function<void(IPatch&)>& functor) override;
std::size_t getSelectedFaceCount() override;
IFace& getSingleSelectedFace() override;
void deselectAll();
void selectPoint(SelectionTest& test, EModifier modifier, bool face) override;
void selectArea(SelectionTest& test, EModifier modifier, bool face) override;
void onManipulationStart() override;
void onManipulationChanged() override;
void onManipulationEnd() override;
void onManipulationCancelled() override;
const WorkZone& getWorkZone() override;
Vector3 getCurrentSelectionCenter() override;
void onPreRender(const VolumeTest& volume) override;
void renderHighlights(IRenderableCollector& collector, const VolumeTest& volume) override
{}
void setRenderSystem(const RenderSystemPtr& renderSystem) override
{}
std::size_t getHighlightFlags() override
{
return Highlight::NoHighlight; // never highlighted
}
const Matrix4& getPivot2World() override;
void toggleSelectionFocus() override;
bool selectionFocusIsActive() override;
AABB getSelectionFocusBounds() override;
// RegisterableModule implementation
const std::string& getName() const override;
const StringSet& getDependencies() const override;
void initialiseModule(const IApplicationContext& ctx) override;
void shutdownModule() override;
ISceneSelectionTester::Ptr createSceneSelectionTester(SelectionMode mode) override;
private:
bool nodeCanBeSelectionTested(const scene::INodePtr& node);
// Sets the selection status of the given selectable. The selection status will
// be propagated to groups if the current selection mode / focus is allowing that
void setSelectionStatus(ISelectable* selectable, bool selected);
// Traverses the scene and adds any selectable nodes matching the given SelectionTest to the "targetList".
void testSelectScene(SelectablesList& targetList, SelectionTest& test,
const VolumeTest& view, SelectionMode mode);
bool higherEntitySelectionPriority() const;
void notifyObservers(const scene::INodePtr& node, bool isComponent);
std::size_t getManipulatorIdForType(IManipulator::Type type);
// Command targets used to connect to the event system
void toggleManipulatorModeCmd(const cmd::ArgumentList& args);
void toggleManipulatorMode(IManipulator::Type type);
void toggleManipulatorModeById(std::size_t manipId);
void activateDefaultMode();
void toggleEntityMode(const cmd::ArgumentList& args);
void toggleGroupPartMode(const cmd::ArgumentList& args);
void toggleMergeActionMode(const cmd::ArgumentList& args);
void toggleSelectionFocus(const cmd::ArgumentList& args);
void toggleComponentMode(ComponentSelectionMode mode);
void toggleComponentModeCmd(const cmd::ArgumentList& args);
void onManipulatorModeChanged();
void onComponentModeChanged();
void checkComponentModeSelectionMode(const ISelectable& selectable); // connects to the selection change signal
void performPointSelection(const SelectablesList& candidates, EModifier modifier);
void onSelectionPerformed();
void deselectCmd(const cmd::ArgumentList& args);
void onMapEvent(IMap::MapEvent ev);
};
}
|