Merge branch 'dragSelection' into 'noggit-shadowlands'

Added drag selection functionality

See merge request prophecy-rp/noggit-red!18
This commit is contained in:
Intemporel
2022-11-15 18:55:31 +00:00
8 changed files with 173 additions and 12 deletions

View File

@@ -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);
}
else
{
doSelection(true);
}
_drag_start_pos = event->pos();
_needs_redraw = true;
_area_selection->setGeometry(QRect(_drag_start_pos, QSize()));
_area_selection->show();
}
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:

View File

@@ -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:

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);
}
}
}
}
}
}
}
}
}

View File

@@ -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();

View File

@@ -73,10 +73,26 @@ namespace Noggit
_radius_slider->setRange (0, 100);
_radius_slider->setSliderPosition (_radius);
radius_layout->addRow (_radius_slider);
radius_layout->addRow(_radius_slider);
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());
@@ -224,7 +240,7 @@ namespace Noggit
multi_select_movement_layout->addRow(multi_select_movement_cb);
multi_select_movement_layout->addRow(object_median_pivot_point);
auto *selectionOptionsBox = new ExpanderWidget( this);
auto *selectionOptionsBox = new ExpanderWidget(this);
selectionOptionsBox->setExpanderTitle("Movement Options");
selectionOptionsBox->setExpanded(_settings->value ("object_editor/movement_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)
{

View File

@@ -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;