Added drag selection functionality
This commit is contained in:
@@ -817,6 +817,9 @@ void MapView::setupObjectEditorUi()
|
||||
|
||||
/* Additional tools */
|
||||
|
||||
/* Area selection */
|
||||
_area_selection = new QRubberBand(QRubberBand::Rectangle, this);
|
||||
|
||||
/* Object Palette */
|
||||
_object_palette = new Noggit::Ui::ObjectPalette(this, this);
|
||||
_object_palette->hide();
|
||||
@@ -4910,6 +4913,12 @@ void MapView::mouseMoveEvent (QMouseEvent* event)
|
||||
|
||||
}
|
||||
|
||||
if (leftMouse && terrainMode == editing_mode::object && _display_mode == display_mode::in_3D && !ImGuizmo::IsUsing())
|
||||
{
|
||||
_needs_redraw = true;
|
||||
_area_selection->setGeometry(QRect(_drag_start_pos, event->pos()).normalized());
|
||||
}
|
||||
|
||||
if (_display_mode == display_mode::in_2D && leftMouse && _mod_alt_down && _mod_shift_down)
|
||||
{
|
||||
strafing = ((relative_movement.dx() / XSENS) / -1) * 5.0f;
|
||||
@@ -4978,18 +4987,15 @@ void MapView::mousePressEvent(QMouseEvent* event)
|
||||
break;
|
||||
}
|
||||
|
||||
if (leftMouse)
|
||||
if (leftMouse && ((terrainMode == editing_mode::object || terrainMode == editing_mode::minimap) && !_mod_ctrl_down))
|
||||
{
|
||||
if ((terrainMode == editing_mode::object || terrainMode == editing_mode::minimap) && !_mod_ctrl_down)
|
||||
{
|
||||
doSelection(false);
|
||||
_drag_start_pos = event->pos();
|
||||
_needs_redraw = true;
|
||||
_area_selection->setGeometry(QRect(_drag_start_pos, QSize()));
|
||||
_area_selection->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
doSelection(true);
|
||||
}
|
||||
}
|
||||
else if (rightMouse)
|
||||
|
||||
if (rightMouse)
|
||||
{
|
||||
look = true;
|
||||
}
|
||||
@@ -5075,6 +5081,32 @@ void MapView::mouseReleaseEvent (QMouseEvent* event)
|
||||
strafing = 0;
|
||||
moving = 0;
|
||||
}
|
||||
|
||||
if ((terrainMode == editing_mode::object || terrainMode == editing_mode::minimap) && !_mod_ctrl_down)
|
||||
{
|
||||
auto drag_end_pos = event->pos();
|
||||
|
||||
if (_drag_start_pos != drag_end_pos && !ImGuizmo::IsUsing())
|
||||
{
|
||||
const std::array<glm::vec2, 2> selection_box
|
||||
{
|
||||
glm::vec2(std::min(_drag_start_pos.x(), drag_end_pos.x()), std::min(_drag_start_pos.y(), drag_end_pos.y())),
|
||||
glm::vec2(std::max(_drag_start_pos.x(), drag_end_pos.x()), std::max(_drag_start_pos.y(), drag_end_pos.y()))
|
||||
};
|
||||
_world->select_objects_in_area(selection_box, !_mod_shift_down, model_view(), projection(), width(), height(), objectEditor->drag_selection_depth(), _camera.position);
|
||||
}
|
||||
else // Do normal selection when we just clicked
|
||||
{
|
||||
doSelection(false);
|
||||
}
|
||||
|
||||
_area_selection->hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
doSelection(true);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Qt::RightButton:
|
||||
|
||||
@@ -126,6 +126,7 @@ private:
|
||||
float moving, strafing, updown, mousedir, turn, lookat;
|
||||
CursorType _cursorType;
|
||||
glm::vec3 _cursor_pos;
|
||||
QPoint _drag_start_pos;
|
||||
float _cursorRotation;
|
||||
bool look, freelook;
|
||||
bool ui_hidden = false;
|
||||
@@ -449,6 +450,8 @@ private:
|
||||
|
||||
OpenGL::Scoped::deferred_upload_buffers<2> _buffers;
|
||||
|
||||
QRubberBand* _area_selection;
|
||||
|
||||
public:
|
||||
|
||||
private:
|
||||
|
||||
@@ -21,6 +21,12 @@ namespace misc
|
||||
point.x <= extents[1].x && point.z <= extents[1].z;
|
||||
}
|
||||
|
||||
bool pointInside(glm::vec2 point, std::array<glm::vec2, 2> const& extents)
|
||||
{
|
||||
return point.x >= extents[0].x && point.y >= extents[0].y &&
|
||||
point.x <= extents[1].x && point.y <= extents[1].y;
|
||||
}
|
||||
|
||||
void minmax(glm::vec3* a, glm::vec3* b)
|
||||
{
|
||||
if (a->x > b->x)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <glm/vec4.hpp>
|
||||
#include <glm/vec2.hpp>
|
||||
#include <noggit/Selection.h>
|
||||
|
||||
|
||||
@@ -55,6 +56,7 @@ namespace misc
|
||||
bool deg_vec3d_equals(math::degrees::vec3 const& v1, math::degrees::vec3 const& v2);
|
||||
|
||||
bool pointInside(glm::vec3 point, std::array<glm::vec3, 2> const& extents);
|
||||
bool pointInside(glm::vec2 point, std::array<glm::vec2, 2> const& extents);
|
||||
void minmax(glm::vec3* a, glm::vec3* b);
|
||||
|
||||
inline int rounded_int_div(int value, int div)
|
||||
|
||||
@@ -2976,3 +2976,72 @@ void World::notifyTileRendererOnSelectedTextureChange()
|
||||
}
|
||||
}
|
||||
|
||||
void World::select_objects_in_area(
|
||||
const std::array<glm::vec2, 2> selection_box,
|
||||
bool reset_selection,
|
||||
glm::mat4x4 view,
|
||||
glm::mat4x4 projection,
|
||||
int viewport_width,
|
||||
int viewport_height,
|
||||
float user_depth,
|
||||
glm::vec3 camera_position)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
if (reset_selection)
|
||||
{
|
||||
this->reset_selection();
|
||||
}
|
||||
|
||||
for (auto& map_object : _loaded_tiles_buffer)
|
||||
{
|
||||
MapTile* tile = map_object.second;
|
||||
|
||||
if (!tile)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto& pair : tile->getObjectInstances())
|
||||
{
|
||||
if (pair.second[0]->which() == eMODEL)
|
||||
{
|
||||
for (auto& instance : pair.second)
|
||||
{
|
||||
auto model = instance->transformMatrix();
|
||||
glm::mat4 VPmatrix = projection * view;
|
||||
glm::vec4 screenPos = VPmatrix * glm::vec4(instance->pos, 1.0f);
|
||||
screenPos.x /= screenPos.w;
|
||||
screenPos.y /= screenPos.w;
|
||||
|
||||
screenPos.x = (screenPos.x + 1.0f) / 2.0f;
|
||||
screenPos.y = (screenPos.y + 1.0f) / 2.0f;
|
||||
screenPos.y = 1 - screenPos.y;
|
||||
|
||||
screenPos.x *= viewport_width;
|
||||
screenPos.y *= viewport_height;
|
||||
|
||||
auto depth = glm::distance(camera_position, instance->pos);
|
||||
if (depth <= user_depth)
|
||||
{
|
||||
const glm::vec2 screenPos2D = glm::vec2(screenPos);
|
||||
if (misc::pointInside(screenPos2D, selection_box))
|
||||
{
|
||||
auto uid = instance->uid;
|
||||
auto modelInstance = _model_instance_storage.get_instance(uid);
|
||||
if (modelInstance && modelInstance.value().index() == eEntry_Object) {
|
||||
auto obj = std::get<selected_object_type>(modelInstance.value());
|
||||
auto model_instance = static_cast<ModelInstance*>(obj);
|
||||
|
||||
if (!is_selected(obj) && !model_instance->model->is_hidden())
|
||||
{
|
||||
this->add_to_selection(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -356,6 +356,17 @@ public:
|
||||
unsigned getNumLoadedTiles() const { return _n_loaded_tiles; };
|
||||
unsigned getNumRenderedTiles() const { return _n_rendered_tiles; };
|
||||
|
||||
void select_objects_in_area(
|
||||
const std::array<glm::vec2, 2> selection_box,
|
||||
bool reset_selection,
|
||||
glm::mat4x4 view,
|
||||
glm::mat4x4 projection,
|
||||
int viewport_width,
|
||||
int viewport_height,
|
||||
float user_depth,
|
||||
glm::vec3 camera_position
|
||||
);
|
||||
|
||||
protected:
|
||||
void update_models_by_filename();
|
||||
|
||||
|
||||
@@ -77,6 +77,22 @@ namespace Noggit
|
||||
radius_layout->addRow(_radius_spin);
|
||||
layout->addWidget(radius_group);
|
||||
|
||||
QGroupBox* drag_selection_depth_group = new QGroupBox("Drag Selection Depth");
|
||||
auto drag_selection_depth_layout = new QFormLayout(drag_selection_depth_group);
|
||||
|
||||
_drag_selection_depth_spin = new QDoubleSpinBox(this);
|
||||
_drag_selection_depth_spin->setRange(1.0f, 3000.0f);
|
||||
_drag_selection_depth_spin->setDecimals(2);
|
||||
_drag_selection_depth_spin->setValue(_drag_selection_depth);
|
||||
|
||||
_drag_selection_depth_slider = new QSlider(Qt::Orientation::Horizontal, this);
|
||||
_drag_selection_depth_slider->setRange(1.0f, 3000.0f);
|
||||
_drag_selection_depth_slider->setSliderPosition(_drag_selection_depth);
|
||||
|
||||
drag_selection_depth_layout->addRow(_drag_selection_depth_slider);
|
||||
drag_selection_depth_layout->addRow(_drag_selection_depth_spin);
|
||||
layout->addWidget(drag_selection_depth_group);
|
||||
|
||||
auto *copyBox = new ExpanderWidget( this);
|
||||
copyBox->setExpanderTitle("Copy options");
|
||||
copyBox->setExpanded(_settings->value ("object_editor/copy_options", false).toBool());
|
||||
@@ -347,6 +363,23 @@ namespace Noggit
|
||||
}
|
||||
);
|
||||
|
||||
connect(_drag_selection_depth_spin, qOverload<double>(&QDoubleSpinBox::valueChanged)
|
||||
, [&] (double v)
|
||||
{
|
||||
_drag_selection_depth = v;
|
||||
QSignalBlocker const blocker(_drag_selection_depth_slider);
|
||||
_drag_selection_depth_slider->setSliderPosition((int)std::round(v));
|
||||
}
|
||||
);
|
||||
connect(_drag_selection_depth_slider, &QSlider::valueChanged
|
||||
, [&](int v)
|
||||
{
|
||||
_drag_selection_depth = v;
|
||||
QSignalBlocker const blocker(_drag_selection_depth_spin);
|
||||
_drag_selection_depth_spin->setValue(v);
|
||||
}
|
||||
);
|
||||
|
||||
connect ( rotRangeStart, qOverload<double> (&QDoubleSpinBox::valueChanged)
|
||||
, [=] (double v)
|
||||
{
|
||||
|
||||
@@ -77,6 +77,8 @@ namespace Noggit
|
||||
|
||||
float brushRadius() const { return _radius; }
|
||||
|
||||
float drag_selection_depth() const { return _drag_selection_depth; }
|
||||
|
||||
model_import *modelImport;
|
||||
rotation_editor* rotationEditor;
|
||||
helper_models* helper_models_widget;
|
||||
@@ -84,11 +86,14 @@ namespace Noggit
|
||||
|
||||
private:
|
||||
float _radius = 0.01f;
|
||||
float _drag_selection_depth = 100.0f;
|
||||
|
||||
MapView* _map_view;
|
||||
|
||||
QSlider* _radius_slider;
|
||||
QDoubleSpinBox* _radius_spin;
|
||||
QSlider* _drag_selection_depth_slider;
|
||||
QDoubleSpinBox* _drag_selection_depth_spin;
|
||||
|
||||
QSettings* _settings;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user