Merge branch 'dragSelection' into 'noggit-shadowlands'
Added drag selection functionality See merge request prophecy-rp/noggit-red!18
This commit is contained in:
@@ -817,6 +817,9 @@ void MapView::setupObjectEditorUi()
|
|||||||
|
|
||||||
/* Additional tools */
|
/* Additional tools */
|
||||||
|
|
||||||
|
/* Area selection */
|
||||||
|
_area_selection = new QRubberBand(QRubberBand::Rectangle, this);
|
||||||
|
|
||||||
/* Object Palette */
|
/* Object Palette */
|
||||||
_object_palette = new Noggit::Ui::ObjectPalette(this, this);
|
_object_palette = new Noggit::Ui::ObjectPalette(this, this);
|
||||||
_object_palette->hide();
|
_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)
|
if (_display_mode == display_mode::in_2D && leftMouse && _mod_alt_down && _mod_shift_down)
|
||||||
{
|
{
|
||||||
strafing = ((relative_movement.dx() / XSENS) / -1) * 5.0f;
|
strafing = ((relative_movement.dx() / XSENS) / -1) * 5.0f;
|
||||||
@@ -4978,18 +4987,15 @@ void MapView::mousePressEvent(QMouseEvent* event)
|
|||||||
break;
|
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)
|
_drag_start_pos = event->pos();
|
||||||
{
|
_needs_redraw = true;
|
||||||
doSelection(false);
|
_area_selection->setGeometry(QRect(_drag_start_pos, QSize()));
|
||||||
|
_area_selection->show();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
if (rightMouse)
|
||||||
doSelection(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (rightMouse)
|
|
||||||
{
|
{
|
||||||
look = true;
|
look = true;
|
||||||
}
|
}
|
||||||
@@ -5075,6 +5081,32 @@ void MapView::mouseReleaseEvent (QMouseEvent* event)
|
|||||||
strafing = 0;
|
strafing = 0;
|
||||||
moving = 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;
|
break;
|
||||||
|
|
||||||
case Qt::RightButton:
|
case Qt::RightButton:
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ private:
|
|||||||
float moving, strafing, updown, mousedir, turn, lookat;
|
float moving, strafing, updown, mousedir, turn, lookat;
|
||||||
CursorType _cursorType;
|
CursorType _cursorType;
|
||||||
glm::vec3 _cursor_pos;
|
glm::vec3 _cursor_pos;
|
||||||
|
QPoint _drag_start_pos;
|
||||||
float _cursorRotation;
|
float _cursorRotation;
|
||||||
bool look, freelook;
|
bool look, freelook;
|
||||||
bool ui_hidden = false;
|
bool ui_hidden = false;
|
||||||
@@ -449,6 +450,8 @@ private:
|
|||||||
|
|
||||||
OpenGL::Scoped::deferred_upload_buffers<2> _buffers;
|
OpenGL::Scoped::deferred_upload_buffers<2> _buffers;
|
||||||
|
|
||||||
|
QRubberBand* _area_selection;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ namespace misc
|
|||||||
point.x <= extents[1].x && point.z <= extents[1].z;
|
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)
|
void minmax(glm::vec3* a, glm::vec3* b)
|
||||||
{
|
{
|
||||||
if (a->x > b->x)
|
if (a->x > b->x)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <glm/vec4.hpp>
|
#include <glm/vec4.hpp>
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
#include <noggit/Selection.h>
|
#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 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::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);
|
void minmax(glm::vec3* a, glm::vec3* b);
|
||||||
|
|
||||||
inline int rounded_int_div(int value, int div)
|
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 getNumLoadedTiles() const { return _n_loaded_tiles; };
|
||||||
unsigned getNumRenderedTiles() const { return _n_rendered_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:
|
protected:
|
||||||
void update_models_by_filename();
|
void update_models_by_filename();
|
||||||
|
|
||||||
|
|||||||
@@ -73,10 +73,26 @@ namespace Noggit
|
|||||||
_radius_slider->setRange (0, 100);
|
_radius_slider->setRange (0, 100);
|
||||||
_radius_slider->setSliderPosition (_radius);
|
_radius_slider->setSliderPosition (_radius);
|
||||||
|
|
||||||
radius_layout->addRow (_radius_slider);
|
radius_layout->addRow(_radius_slider);
|
||||||
radius_layout->addRow(_radius_spin);
|
radius_layout->addRow(_radius_spin);
|
||||||
layout->addWidget(radius_group);
|
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);
|
auto *copyBox = new ExpanderWidget( this);
|
||||||
copyBox->setExpanderTitle("Copy options");
|
copyBox->setExpanderTitle("Copy options");
|
||||||
copyBox->setExpanded(_settings->value ("object_editor/copy_options", false).toBool());
|
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(multi_select_movement_cb);
|
||||||
multi_select_movement_layout->addRow(object_median_pivot_point);
|
multi_select_movement_layout->addRow(object_median_pivot_point);
|
||||||
|
|
||||||
auto *selectionOptionsBox = new ExpanderWidget( this);
|
auto *selectionOptionsBox = new ExpanderWidget(this);
|
||||||
selectionOptionsBox->setExpanderTitle("Movement Options");
|
selectionOptionsBox->setExpanderTitle("Movement Options");
|
||||||
selectionOptionsBox->setExpanded(_settings->value ("object_editor/movement_options", false).toBool());
|
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)
|
connect ( rotRangeStart, qOverload<double> (&QDoubleSpinBox::valueChanged)
|
||||||
, [=] (double v)
|
, [=] (double v)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ namespace Noggit
|
|||||||
|
|
||||||
float brushRadius() const { return _radius; }
|
float brushRadius() const { return _radius; }
|
||||||
|
|
||||||
|
float drag_selection_depth() const { return _drag_selection_depth; }
|
||||||
|
|
||||||
model_import *modelImport;
|
model_import *modelImport;
|
||||||
rotation_editor* rotationEditor;
|
rotation_editor* rotationEditor;
|
||||||
helper_models* helper_models_widget;
|
helper_models* helper_models_widget;
|
||||||
@@ -84,11 +86,14 @@ namespace Noggit
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
float _radius = 0.01f;
|
float _radius = 0.01f;
|
||||||
|
float _drag_selection_depth = 100.0f;
|
||||||
|
|
||||||
MapView* _map_view;
|
MapView* _map_view;
|
||||||
|
|
||||||
QSlider* _radius_slider;
|
QSlider* _radius_slider;
|
||||||
QDoubleSpinBox* _radius_spin;
|
QDoubleSpinBox* _radius_spin;
|
||||||
|
QSlider* _drag_selection_depth_slider;
|
||||||
|
QDoubleSpinBox* _drag_selection_depth_spin;
|
||||||
|
|
||||||
QSettings* _settings;
|
QSettings* _settings;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user