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
|
#include "DragManipulator.h"
#include "selection/SelectionPool.h"
#include "selection/SelectionTestWalkers.h"
#include "selection/algorithm/Planes.h"
namespace selection
{
namespace
{
// Predicate function used to pick selectable Sectables only when drag-manipulating
bool filterSelectedItemsOnly(ISelectable* selectable)
{
return selectable->isSelected();
}
}
DragManipulator::DragManipulator(ManipulationPivot& pivot, SelectionSystem& selectionSystem, ISceneSelectionTesterFactory& factory) :
_pivot(pivot),
_selectionSystem(selectionSystem),
_testerFactory(factory),
_freeResizeComponent(_resizeTranslatable),
_resizeModeActive(false),
_freeDragComponent(_dragTranslatable),
_dragTranslatable(SelectionTranslator::TranslationCallback())
{}
DragManipulator::Type DragManipulator::getType() const
{
return Drag;
}
DragManipulator::Component* DragManipulator::getActiveComponent()
{
return _dragSelectable.isSelected() ? &_freeDragComponent : &_freeResizeComponent;
}
void DragManipulator::testSelect(SelectionTest& test, const Matrix4& pivot2world)
{
_resizeModeActive = false;
// No drag manipulation in merge mode
if (_selectionSystem.getSelectionMode() == SelectionMode::MergeAction) return;
SelectionPool selector;
switch (_selectionSystem.getSelectionMode())
{
case SelectionMode::Primitive:
testSelectPrimitiveMode(test.getVolume(), test, selector);
break;
case SelectionMode::GroupPart:
testSelectGroupPartMode(test.getVolume(), test, selector);
break;
case SelectionMode::Entity:
testSelectEntityMode(test.getVolume(), test, selector);
break;
case SelectionMode::Component:
testSelectComponentMode(test.getVolume(), test, selector);
break;
default:
return;
};
for (auto& [_, selectable] : selector)
{
selectable->setSelected(true);
}
}
bool DragManipulator::testSelectedItemsInScene(SelectionMode mode, const VolumeTest& view, SelectionTest& test)
{
auto tester = _testerFactory.createSceneSelectionTester(mode);
tester->testSelectSceneWithFilter(view, test, filterSelectedItemsOnly);
return tester->hasSelectables();
}
void DragManipulator::testSelectPrimitiveMode(const VolumeTest& view, SelectionTest& test, SelectionPool& selector)
{
// If testing for entities and worldspawn primitives fails check for group children too
if (testSelectedItemsInScene(SelectionMode::Primitive, view, test) ||
testSelectedItemsInScene(SelectionMode::GroupPart, view, test))
{
selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
return;
}
// all direct hits failed, check for drag-selectable faces
_resizeModeActive = algorithm::testSelectPlanes(selector, test);
}
void DragManipulator::testSelectGroupPartMode(const VolumeTest& view, SelectionTest& test, SelectionPool& selector)
{
// Find all non-worldspawn child primitives that are selectable
if (testSelectedItemsInScene(SelectionMode::GroupPart, view, test))
{
// Found a selectable primitive
selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
return;
}
// Check for selectable faces
_resizeModeActive = algorithm::testSelectPlanes(selector, test);
}
void DragManipulator::testSelectEntityMode(const VolumeTest& view, SelectionTest& test, SelectionPool& selector)
{
// Check, if an entity could be found
if (testSelectedItemsInScene(SelectionMode::Entity, view, test))
{
selector.addSelectable(SelectionIntersection(0, 0), &_dragSelectable);
return;
}
// Check for selectable faces
_resizeModeActive = algorithm::testSelectPlanes(selector, test);
}
void DragManipulator::testSelectComponentMode(const VolumeTest& view, SelectionTest& test, SelectionPool& selector)
{
auto tester = _testerFactory.createSceneSelectionTester(SelectionMode::Component);
tester->testSelectScene(view, test); // don't restrict drag-selecting to selected components
tester->foreachSelectable([&](auto selectable)
{
// greebo: Transient component selection: clicking an unselected
// component will deselect all previously selected components beforehand
if (!selectable->isSelected())
{
_selectionSystem.setSelectedAllComponents(false);
}
selector.addSelectable(SelectionIntersection(0, 0), selectable);
_dragSelectable.setSelected(true);
});
}
void DragManipulator::setSelected(bool select)
{
_resizeModeActive = select;
_dragSelectable.setSelected(select);
}
bool DragManipulator::isSelected() const
{
return _resizeModeActive || _dragSelectable.isSelected();
}
}
|