This commit is contained in:
T1ti
2024-01-06 23:40:08 +01:00
parent 882179f675
commit 958deca368
5 changed files with 229 additions and 50 deletions

View File

@@ -5705,14 +5705,9 @@ void MapView::ShowContextMenu(QPoint pos)
if (!last_entry.value().index() == eEntry_Object)
return;
// Only works with m2 doodads
auto obj = std::get<selected_object_type>(last_entry.value());
auto model_name = obj->instance_model()->file_key().filepath();
// auto models = _world->get_models_by_filename()[model_name];
// std::vector< uint32_t> objects_to_select;
//makeCurrent();
//OpenGL::context::scoped_setter const _(::gl, context());
_world->reset_selection();
@@ -5754,21 +5749,12 @@ void MapView::ShowContextMenu(QPoint pos)
{
if (_world->has_selection())
{
for (auto& selection : _world->current_selection())
for (auto& obj : _world->get_selected_objects())
{
if (selection.index() != eEntry_Object)
continue;
auto obj = std::get<selected_object_type>(selection);
if (obj->which() == eMODEL)
{
static_cast<ModelInstance*>(obj)->model->hide();
}
else if (obj->which() == eWMO)
{
static_cast<WMOInstance*>(obj)->wmo->hide();
}
}
}
});
@@ -5783,8 +5769,6 @@ void MapView::ShowContextMenu(QPoint pos)
action_palette_add.setEnabled(_world->get_selected_model_count() == 1);
QObject::connect(&action_palette_add, &QAction::triggered, [=]()
{
auto last_entry = _world->get_last_selected_model();
if (last_entry)
{
@@ -5823,13 +5807,8 @@ void MapView::ShowContextMenu(QPoint pos)
auto replace_path = replace_obj->instance_model()->file_key();
// iterate selection (objects to replace)
for (auto& entry : _world->current_selection())
for (auto& source_obj : _world->get_selected_objects())
{
if (entry.index() == eEntry_Object)
{
auto source_obj = std::get<selected_object_type>(entry);
//SceneObject* source_scene_obj = source_obj;
math::degrees::vec3 source_rot(math::degrees(0)._, math::degrees(0)._, math::degrees(0)._);
source_rot = source_obj->dir;
@@ -5882,8 +5861,6 @@ void MapView::ShowContextMenu(QPoint pos)
new_obj->model->waitForChildrenLoaded();
new_obj->recalcExtents();
}
}
}
// can cause the usual crash of deleting models overlapping unloaded tiles.
DeleteSelectedObjects();
@@ -5908,13 +5885,26 @@ void MapView::ShowContextMenu(QPoint pos)
menu->addSeparator();
// TODO
QAction action_6("Group Selected Objects TODO", this);
menu->addAction(&action_6);
action_6.setEnabled(_world->has_multiple_model_selected() && false); // TODO, some "notgrouped" condition
QAction action_group("Group Selected Objects TODO", this);
menu->addAction(&action_group);
action_group.setEnabled(_world->has_multiple_model_selected() && true); // TODO, some "notgrouped" condition
QObject::connect(&action_snap, &QAction::triggered, [=]()
{
_world->add_object_group();
//auto selected_objects = _world->get_selected_objects();
//for (auto selected_obj : selected_objects)
//{
//
//}
});
QAction action_ungroup("Ungroup Selected Objects TODO", this);
QAction action_7("Ungroup Selected Objects TODO", this);
menu->addSeparator();
menu->exec(mapToGlobal(pos)); // synch
// menu->popup(mapToGlobal(pos)); // asynch

View File

@@ -74,4 +74,118 @@ void selected_chunk_type::updateDetails(Noggit::Ui::detail_infos* detail_widget)
select_info << "</span><br>";
detail_widget->setText(select_info.str());
}
}
selection_group::selection_group(std::vector<selected_object_type> selected_objects, World* world)
: _world(world)
{
_object_count = selected_objects.size();
if (!_object_count)
return;
// default group extents to first obj
_group_extents = selected_objects.front()->getExtents();
_members_uid.reserve(selected_objects.size());
for (auto& selected_obj : selected_objects)
{
_members_uid.push_back(selected_obj->uid);
if (selected_obj->getExtents()[0].x < _group_extents[0].x)
_group_extents[0].x = selected_obj->extents[0].x;
if (selected_obj->getExtents()[0].y < _group_extents[0].y)
_group_extents[0].y = selected_obj->extents[0].y;
if (selected_obj->getExtents()[0].z < _group_extents[0].z)
_group_extents[0].z = selected_obj->extents[0].z;
if (selected_obj->getExtents()[1].x > _group_extents[1].x)
_group_extents[1].x = selected_obj->extents[1].x;
if (selected_obj->getExtents()[1].y > _group_extents[1].y)
_group_extents[1].y = selected_obj->extents[1].y;
if (selected_obj->getExtents()[1].z > _group_extents[1].z)
_group_extents[1].z = selected_obj->extents[1].z;
}
}
bool selection_group::group_contains_object(selected_object_type object)
{
for (unsigned int member_uid : _members_uid)
{
if (object->uid == member_uid)
return true;
}
return false;
}
void selection_group::select_group()
{
for (unsigned int obj_uid : _members_uid)
{
std::optional<selection_type> obj = _world->get_model(obj_uid);
if (!obj)
continue;
SceneObject* instance = std::get<SceneObject*>(obj.value());
if (_world->is_selected(instance))
continue;
_world->add_to_selection(obj.value(), true);
}
}
void selection_group::unselect_group()
{
for (unsigned int obj_uid : _members_uid)
{
// don't need to check if it's not selected
_world->remove_from_selection(obj_uid);
/*
std::optional<selection_type> obj = _world->get_model(obj_uid);
if (!obj)
continue;
SceneObject* instance = std::get<SceneObject*>(obj.value());
if (_world->is_selected(instance))
_world->remove_from_selection(obj.value());
*/
}
}
void selection_group::move_group()
{
// _world->select_objects_in_area
}
void selection_group::recalcExtents()
{
for (unsigned int obj_uid : _members_uid)
{
std::optional<selection_type> obj = _world->get_model(obj_uid);
if (!obj)
continue;
SceneObject* instance = std::get<SceneObject*>(obj.value());
// min = glm::min(min, point);
if (instance->getExtents()[0].x < _group_extents[0].x)
_group_extents[0].x = instance->extents[0].x;
if (instance->getExtents()[0].y < _group_extents[0].y)
_group_extents[0].y = instance->extents[0].y;
if (instance->getExtents()[0].z < _group_extents[0].z)
_group_extents[0].z = instance->extents[0].z;
if (instance->getExtents()[1].x > _group_extents[1].x)
_group_extents[1].x = instance->extents[1].x;
if (instance->getExtents()[1].y > _group_extents[1].y)
_group_extents[1].y = instance->extents[1].y;
if (instance->getExtents()[1].z > _group_extents[1].z)
_group_extents[1].z = instance->extents[1].z;
}
}

View File

@@ -7,7 +7,10 @@
#include <vector>
#include <QString>
// #include <noggit/World.h>
class World;
class SceneObject;
class MapChunk;
@@ -48,22 +51,47 @@ enum eSelectionEntryTypes
eEntry_MapChunk
};
using selection_entry = std::pair<float, selection_type>;
using selection_result = std::vector<selection_entry>;
struct selection_group
class selection_group
{
selection_group()
{
};
public:
selection_group(std::vector<selected_object_type> selected_objects, World* world);
void add_member(selected_object_type);
void add_member(selected_object_type object);
void set_selected_as_group(std::vector<selection_type> selection);
bool group_contains_object(selected_object_type object);
void select_group();
void unselect_group();
// void set_selected_as_group(std::vector<selected_object_type> selection);
void copy_group(); // create and save a new selection group from copied objects
std::vector<unsigned int> object_members; // uids
void move_group();
void scale_group();
void rotate_group();
std::array<glm::vec3, 2> extents;
};
std::vector<unsigned int> const& getObjects() const { return _members_uid; }
[[nodiscard]]
std::array<glm::vec3, 2> const& getExtents() { return _group_extents; } // ensureExtents();
private:
void recalcExtents();
std::vector<unsigned int> _members_uid; // uids
// std::vector<SceneObject*> _object_members;
std::array<glm::vec3, 2> _group_extents;
unsigned int _object_count = 0;
World* _world;
};
using selection_entry = std::pair<float, selection_type>;
using selection_result = std::vector<selection_entry>;

View File

@@ -232,6 +232,25 @@ std::optional<selection_type> World::get_last_selected_model() const
? std::optional<selection_type>() : std::optional<selection_type> (*it);
}
std::vector<selected_object_type> const& World::get_selected_objects() const
{
// std::vector<selected_object_type> objects(_selected_model_count);
std::vector<selected_object_type> objects;
objects.reserve(_selected_model_count);
ZoneScoped;
for (auto& entry : _current_selection)
{
if (entry.index() == eEntry_Object)
{
auto obj = std::get<selected_object_type>(entry);
objects.push_back(obj);
}
}
return objects;
}
glm::vec3 getBarycentricCoordinatesAt(
const glm::vec3& a,
const glm::vec3& b,
@@ -490,17 +509,31 @@ void World::set_current_selection(selection_type entry)
_current_selection.push_back(entry);
_multi_select_pivot = std::nullopt;
_selected_model_count = entry.index() == eEntry_MapChunk ? 0 : 1;
_selected_model_count = entry.index() != eEntry_Object ? 0 : 1;
}
void World::add_to_selection(selection_type entry)
void World::add_to_selection(selection_type entry, bool skip_group)
{
ZoneScoped;
if (entry.index() != eEntry_MapChunk)
if (entry.index() == eEntry_Object)
{
_selected_model_count++;
}
// check if it is in a group
if (!skip_group)
{
auto obj = std::get<selected_object_type>(entry);
for (auto& group : _selection_groups)
{
if (group.group_contains_object(obj))
{
// this then calls add_to_selection() with skip_group = true to avoid repetition
group.select_group();
break;
}
}
}
}
_current_selection.push_back(entry);
update_selection_pivot();
}
@@ -511,7 +544,7 @@ void World::remove_from_selection(selection_type entry)
std::vector<selection_type>::iterator position = std::find(_current_selection.begin(), _current_selection.end(), entry);
if (position != _current_selection.end())
{
if (entry.index() != eEntry_MapChunk)
if (entry.index() == eEntry_Object)
{
_selected_model_count--;
}
@@ -3355,4 +3388,14 @@ void World::select_objects_in_area(
}
}
}
}
}
void World::add_object_group()
{
// auto selected_objects = get_selected_objects();
selection_group selection_group(get_selected_objects(), this);
_selection_groups.push_back(selection_group);
// write group to project
}

View File

@@ -61,7 +61,7 @@ protected:
// std::unordered_map<std::string, std::vector<ModelInstance*>> _models_by_filename;
Noggit::world_model_instances_storage _model_instance_storage;
Noggit::world_tile_update_queue _tile_update_queue;
std::vector< selection_group> _selection_groups;
std::vector<selection_group> _selection_groups;
public:
MapIndex mapIndex;
@@ -123,6 +123,7 @@ public:
bool is_selected(selection_type selection) const;
bool is_selected(std::uint32_t uid) const;
std::vector<selection_type> const& current_selection() const { return _current_selection; }
std::vector<selected_object_type> const& get_selected_objects() const;
std::optional<selection_type> get_last_selected_model() const;
bool has_selection() const { return !_current_selection.empty(); }
bool has_multiple_model_selected() const { return _selected_model_count > 1; }
@@ -130,7 +131,7 @@ public:
// Unused in Red, models are now iterated by adt because of the occlusion check
// std::unordered_map<std::string, std::vector<ModelInstance*>> get_models_by_filename() const& { return _models_by_filename; }
void set_current_selection(selection_type entry);
void add_to_selection(selection_type entry);
void add_to_selection(selection_type entry, bool skip_group = false);
void remove_from_selection(selection_type entry);
void remove_from_selection(std::uint32_t uid);
void reset_selection();
@@ -389,6 +390,9 @@ public:
glm::vec3 camera_position
);
void add_object_group();
void delete_object_group();
protected:
// void update_models_by_filename();