Cut WIP:
* ObjectList & Selection: Show Connectors in the Scene, when CutConnectors Item is selected * ObjectList: refactoring: extract the adding of volumes to the add_volumes_to_object_in_list() * If some connector is selected on 3dScene -> select all connectors of this object * GLGizmoScale3D : check if grabber is enabled, when do rendering + GLGizmoCut: refactoring : split render_cut_plane_grabbers to several functions
This commit is contained in:
parent
d1c871758b
commit
a8440db5ec
10 changed files with 268 additions and 232 deletions
|
@ -403,6 +403,13 @@ MeshErrorsInfo ObjectList::get_mesh_errors_info(const int obj_idx, const int vol
|
|||
if (obj_idx < 0)
|
||||
return { {}, {} }; // hide tooltip
|
||||
|
||||
const ModelObject* object = (*m_objects)[obj_idx];
|
||||
if (vol_idx != -1 && vol_idx >= int(object->volumes.size())) {
|
||||
if (sidebar_info)
|
||||
*sidebar_info = _L("Wrong volume index ");
|
||||
return { {}, {} }; // hide tooltip
|
||||
}
|
||||
|
||||
const TriangleMeshStats& stats = vol_idx == -1 ?
|
||||
(*m_objects)[obj_idx]->get_object_stl_stats() :
|
||||
(*m_objects)[obj_idx]->volumes[vol_idx]->mesh().stats();
|
||||
|
@ -2075,30 +2082,11 @@ void ObjectList::split()
|
|||
|
||||
volume->split(nozzle_dmrs_cnt);
|
||||
|
||||
(*m_objects)[obj_idx]->input_file.clear();
|
||||
|
||||
wxBusyCursor wait;
|
||||
|
||||
auto model_object = (*m_objects)[obj_idx];
|
||||
|
||||
auto parent = m_objects_model->GetTopParent(item);
|
||||
if (parent)
|
||||
m_objects_model->DeleteVolumeChildren(parent);
|
||||
else
|
||||
parent = item;
|
||||
|
||||
for (const ModelVolume* volume : model_object->volumes) {
|
||||
const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(parent, from_u8(volume->name),
|
||||
volume->type(),// is_modifier() ? ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART,
|
||||
get_warning_icon_name(volume->mesh().stats()),
|
||||
volume->config.has("extruder") ? volume->config.extruder() : 0,
|
||||
false);
|
||||
// add settings to the part, if it has those
|
||||
add_settings_item(vol_item, &volume->config.get());
|
||||
}
|
||||
|
||||
model_object->input_file.clear();
|
||||
|
||||
if (parent == item)
|
||||
Expand(parent);
|
||||
add_volumes_to_object_in_list(obj_idx);
|
||||
|
||||
changed_object(obj_idx);
|
||||
// update printable state for new volumes on canvas3D
|
||||
|
@ -2524,7 +2512,14 @@ void ObjectList::part_selection_changed()
|
|||
|
||||
GLGizmosManager& gizmos_mgr = wxGetApp().plater()->canvas3D()->get_gizmos_manager();
|
||||
|
||||
if ( multiple_selection() || (item && m_objects_model->GetItemType(item) == itInstanceRoot )) {
|
||||
if (item && m_objects_model->GetItemType(item) == itInfo && m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors) {
|
||||
og_name = _L("Cut Connectors information");
|
||||
|
||||
update_and_show_manipulations = true;
|
||||
enable_manipulation = false;
|
||||
disable_ununiform_scale = true;
|
||||
}
|
||||
else if ( multiple_selection() || (item && m_objects_model->GetItemType(item) == itInstanceRoot )) {
|
||||
og_name = _L("Group manipulation");
|
||||
|
||||
const Selection& selection = scene_selection();
|
||||
|
@ -2575,11 +2570,12 @@ void ObjectList::part_selection_changed()
|
|||
const wxDataViewItem parent = m_objects_model->GetParent(item);
|
||||
const ItemType parent_type = m_objects_model->GetItemType(parent);
|
||||
obj_idx = m_objects_model->GetObjectIdByItem(item);
|
||||
ModelObject* object = (*m_objects)[obj_idx];
|
||||
|
||||
if (parent == wxDataViewItem(nullptr)
|
||||
|| type == itInfo) {
|
||||
og_name = _L("Object manipulation");
|
||||
m_config = &(*m_objects)[obj_idx]->config;
|
||||
m_config = &object->config;
|
||||
update_and_show_manipulations = true;
|
||||
|
||||
if (type == itInfo) {
|
||||
|
@ -2602,23 +2598,23 @@ void ObjectList::part_selection_changed()
|
|||
gizmos_mgr.open_gizmo(gizmo_type);
|
||||
break;
|
||||
}
|
||||
case InfoItemType::Sinking: { break; }
|
||||
case InfoItemType::Sinking:
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
else
|
||||
disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut();
|
||||
disable_ss_manipulation = object->is_cut();
|
||||
}
|
||||
else {
|
||||
if (type & itSettings) {
|
||||
if (parent_type & itObject) {
|
||||
og_name = _L("Object Settings to modify");
|
||||
m_config = &(*m_objects)[obj_idx]->config;
|
||||
m_config = &object->config;
|
||||
}
|
||||
else if (parent_type & itVolume) {
|
||||
og_name = _L("Part Settings to modify");
|
||||
volume_id = m_objects_model->GetVolumeIdByItem(parent);
|
||||
m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config;
|
||||
m_config = &object->volumes[volume_id]->config;
|
||||
}
|
||||
else if (parent_type & itLayer) {
|
||||
og_name = _L("Layer range Settings to modify");
|
||||
|
@ -2629,17 +2625,17 @@ void ObjectList::part_selection_changed()
|
|||
else if (type & itVolume) {
|
||||
og_name = _L("Part manipulation");
|
||||
volume_id = m_objects_model->GetVolumeIdByItem(item);
|
||||
m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config;
|
||||
m_config = &object->volumes[volume_id]->config;
|
||||
update_and_show_manipulations = true;
|
||||
enable_manipulation = !(*m_objects)[obj_idx]->is_cut();
|
||||
enable_manipulation = !(object->is_cut() && object->volumes[volume_id]->is_cut_connector());
|
||||
}
|
||||
else if (type & itInstance) {
|
||||
og_name = _L("Instance manipulation");
|
||||
update_and_show_manipulations = true;
|
||||
|
||||
// fill m_config by object's values
|
||||
m_config = &(*m_objects)[obj_idx]->config;
|
||||
disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut();
|
||||
m_config = &object->config;
|
||||
disable_ss_manipulation = object->is_cut();
|
||||
}
|
||||
else if (type & (itLayerRoot|itLayer)) {
|
||||
og_name = type & itLayerRoot ? _L("Height ranges") : _L("Settings for height range");
|
||||
|
@ -2658,7 +2654,6 @@ void ObjectList::part_selection_changed()
|
|||
wxGetApp().obj_manipul()->get_og()->set_name(" " + og_name + " ");
|
||||
|
||||
if (item) {
|
||||
// wxGetApp().obj_manipul()->get_og()->set_value("object_name", m_objects_model->GetName(item));
|
||||
wxGetApp().obj_manipul()->update_item_name(m_objects_model->GetName(item));
|
||||
wxGetApp().obj_manipul()->update_warning_icon_state(get_mesh_errors_info(obj_idx, volume_id));
|
||||
}
|
||||
|
@ -2817,43 +2812,70 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio
|
|||
}
|
||||
}
|
||||
|
||||
static wxString extruder2str(int extruder)
|
||||
{
|
||||
return extruder == 0 ? _L("default") : wxString::Format("%d", extruder);
|
||||
}
|
||||
|
||||
static bool can_add_volumes_to_object(const ModelObject* object)
|
||||
{
|
||||
bool can = object->volumes.size() > 1;
|
||||
|
||||
if (can && object->is_cut()) {
|
||||
int no_connectors_cnt = 0;
|
||||
for (const ModelVolume* v : object->volumes)
|
||||
if (!v->is_cut_connector())
|
||||
no_connectors_cnt++;
|
||||
can = no_connectors_cnt > 1;
|
||||
}
|
||||
|
||||
return can;
|
||||
}
|
||||
|
||||
wxDataViewItemArray ObjectList::add_volumes_to_object_in_list(size_t obj_idx, std::function<bool(const ModelVolume*)> add_to_selection/* = nullptr*/)
|
||||
{
|
||||
wxDataViewItem object_item = m_objects_model->GetItemById(int(obj_idx));
|
||||
m_objects_model->DeleteVolumeChildren(object_item);
|
||||
|
||||
wxDataViewItemArray items;
|
||||
|
||||
const ModelObject* object = (*m_objects)[obj_idx];
|
||||
// add volumes to the object
|
||||
if (can_add_volumes_to_object(object)) {
|
||||
int volume_idx{ -1 };
|
||||
for (const ModelVolume* volume : object->volumes) {
|
||||
++volume_idx;
|
||||
if (object->is_cut() && volume->is_cut_connector())
|
||||
continue;
|
||||
const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(object_item,
|
||||
from_u8(volume->name),
|
||||
volume_idx,
|
||||
volume->type(),
|
||||
get_warning_icon_name(volume->mesh().stats()),
|
||||
extruder2str(volume->config.has("extruder") ? volume->config.extruder() : 0));
|
||||
add_settings_item(vol_item, &volume->config.get());
|
||||
|
||||
if (add_to_selection && add_to_selection(volume))
|
||||
items.Add(vol_item);
|
||||
}
|
||||
Expand(object_item);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed)
|
||||
{
|
||||
auto model_object = (*m_objects)[obj_idx];
|
||||
const wxString& item_name = from_u8(model_object->name);
|
||||
const auto item = m_objects_model->Add(item_name,
|
||||
model_object->config.has("extruder") ? model_object->config.extruder() : 0,
|
||||
const auto item = m_objects_model->AddObject(item_name,
|
||||
extruder2str(model_object->config.has("extruder") ? model_object->config.extruder() : 0),
|
||||
get_warning_icon_name(model_object->mesh().stats()),
|
||||
model_object->is_cut());
|
||||
|
||||
update_info_items(obj_idx, nullptr, call_selection_changed);
|
||||
|
||||
bool can_add_volumes = model_object->volumes.size() > 1;
|
||||
if (can_add_volumes && model_object->is_cut()) {
|
||||
int no_connectors_cnt = 0;
|
||||
for (const ModelVolume* v : model_object->volumes)
|
||||
if (!v->is_cut_connector())
|
||||
no_connectors_cnt++;
|
||||
can_add_volumes = no_connectors_cnt > 1;
|
||||
}
|
||||
|
||||
// add volumes to the object
|
||||
if (can_add_volumes) {
|
||||
for (const ModelVolume* volume : model_object->volumes) {
|
||||
if (model_object->is_cut() && volume->is_cut_connector())
|
||||
continue;
|
||||
const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(item,
|
||||
from_u8(volume->name),
|
||||
volume->type(),
|
||||
get_warning_icon_name(volume->mesh().stats()),
|
||||
volume->config.has("extruder") ? volume->config.extruder() : 0,
|
||||
false);
|
||||
add_settings_item(vol_item, &volume->config.get());
|
||||
}
|
||||
Expand(item);
|
||||
}
|
||||
add_volumes_to_object_in_list(obj_idx);
|
||||
|
||||
// add instances to the object, if it has those
|
||||
if (model_object->instances.size()>1)
|
||||
|
@ -3327,7 +3349,7 @@ void ObjectList::add_layer_item(const t_layer_height_range& range,
|
|||
|
||||
const auto layer_item = m_objects_model->AddLayersChild(layers_item,
|
||||
range,
|
||||
config.opt_int("extruder"),
|
||||
extruder2str(config.opt_int("extruder")),
|
||||
layer_idx);
|
||||
add_settings_item(layer_item, &config);
|
||||
}
|
||||
|
@ -3421,6 +3443,24 @@ bool ObjectList::is_selected(const ItemType type) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ObjectList::is_connectors_item_selected() const
|
||||
{
|
||||
const wxDataViewItem& item = GetSelection();
|
||||
if (item)
|
||||
return m_objects_model->GetItemType(item) == itInfo && m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ObjectList::is_connectors_item_selected(const wxDataViewItemArray& sels) const
|
||||
{
|
||||
for (auto item : sels)
|
||||
if (m_objects_model->GetItemType(item) == itInfo && m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ObjectList::get_selected_layers_range_idx() const
|
||||
{
|
||||
const wxDataViewItem& item = GetSelection();
|
||||
|
@ -3547,11 +3587,18 @@ void ObjectList::update_selections()
|
|||
else {
|
||||
for (auto idx : selection.get_volume_idxs()) {
|
||||
const auto gl_vol = selection.get_volume(idx);
|
||||
if (gl_vol->volume_idx() >= 0)
|
||||
if (gl_vol->volume_idx() >= 0) {
|
||||
// Only add GLVolumes with non-negative volume_ids. GLVolumes with negative volume ids
|
||||
// are not associated with ModelVolumes, but they are temporarily generated by the backend
|
||||
// (for example, SLA supports or SLA pad).
|
||||
sels.Add(m_objects_model->GetItemByVolumeId(gl_vol->object_idx(), gl_vol->volume_idx()));
|
||||
int obj_idx = gl_vol->object_idx();
|
||||
int vol_idx = gl_vol->volume_idx();
|
||||
assert(obj_idx >= 0 && vol_idx >= 0);
|
||||
if (object(obj_idx)->volumes[vol_idx]->is_cut_connector())
|
||||
sels.Add(m_objects_model->GetInfoItemByType(m_objects_model->GetItemById(obj_idx), InfoItemType::CutConnectors));
|
||||
else
|
||||
sels.Add(m_objects_model->GetItemByVolumeId(obj_idx, vol_idx));
|
||||
}
|
||||
}
|
||||
m_selection_mode = smVolume; }
|
||||
}
|
||||
|
@ -3602,7 +3649,7 @@ void ObjectList::update_selections()
|
|||
if (sels.size() == 0 || m_selection_mode & smSettings)
|
||||
m_selection_mode = smUndef;
|
||||
|
||||
if (fix_cut_selection(sels)) {
|
||||
if (fix_cut_selection(sels) || is_connectors_item_selected(sels)) {
|
||||
m_prevent_list_events = true;
|
||||
|
||||
// If some part is selected, unselect all items except of selected parts of the current object
|
||||
|
@ -3616,7 +3663,7 @@ void ObjectList::update_selections()
|
|||
update_selections_on_canvas();
|
||||
|
||||
// to update the toolbar and info sizer
|
||||
if (!GetSelection() || m_objects_model->GetItemType(GetSelection()) == itObject) {
|
||||
if (!GetSelection() || m_objects_model->GetItemType(GetSelection()) == itObject || is_connectors_item_selected()) {
|
||||
auto event = SimpleEvent(EVT_OBJ_LIST_OBJECT_SELECT);
|
||||
event.SetEventObject(this);
|
||||
wxPostEvent(this, event);
|
||||
|
@ -3662,16 +3709,29 @@ void ObjectList::update_selections_on_canvas()
|
|||
volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end());
|
||||
}
|
||||
else if (type == itInfo) {
|
||||
// When selecting an info item, select one instance of the
|
||||
// respective object - a gizmo may want to be opened.
|
||||
int inst_idx = selection.get_instance_idx();
|
||||
int scene_obj_idx = selection.get_object_idx();
|
||||
mode = Selection::Instance;
|
||||
// select first instance, unless an instance of the object is already selected
|
||||
if (scene_obj_idx == -1 || inst_idx == -1 || scene_obj_idx != obj_idx)
|
||||
inst_idx = 0;
|
||||
std::vector<unsigned int> idxs = selection.get_volume_idxs_from_instance(obj_idx, inst_idx);
|
||||
volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end());
|
||||
if (m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors) {
|
||||
mode = Selection::Volume;
|
||||
|
||||
// When selecting CutConnectors info item, select all object volumes, which are marked as a connector
|
||||
const ModelObject* obj = object(obj_idx);
|
||||
for (unsigned int vol_idx = 0; vol_idx < obj->volumes.size(); vol_idx++)
|
||||
if (obj->volumes[vol_idx]->is_cut_connector()) {
|
||||
std::vector<unsigned int> idxs = selection.get_volume_idxs_from_volume(obj_idx, std::max(instance_idx, 0), vol_idx);
|
||||
volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end());
|
||||
}
|
||||
}
|
||||
else {
|
||||
// When selecting an info item, select one instance of the
|
||||
// respective object - a gizmo may want to be opened.
|
||||
int inst_idx = selection.get_instance_idx();
|
||||
int scene_obj_idx = selection.get_object_idx();
|
||||
mode = Selection::Instance;
|
||||
// select first instance, unless an instance of the object is already selected
|
||||
if (scene_obj_idx == -1 || inst_idx == -1 || scene_obj_idx != obj_idx)
|
||||
inst_idx = 0;
|
||||
std::vector<unsigned int> idxs = selection.get_volume_idxs_from_instance(obj_idx, inst_idx);
|
||||
volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4569,33 +4629,14 @@ void ObjectList::set_extruder_for_selected_items(const int extruder) const
|
|||
wxGetApp().plater()->update();
|
||||
}
|
||||
|
||||
wxDataViewItemArray ObjectList::reorder_volumes_and_get_selection(int obj_idx, std::function<bool(const ModelVolume*)> add_to_selection/* = nullptr*/)
|
||||
wxDataViewItemArray ObjectList::reorder_volumes_and_get_selection(size_t obj_idx, std::function<bool(const ModelVolume*)> add_to_selection/* = nullptr*/)
|
||||
{
|
||||
wxDataViewItemArray items;
|
||||
(*m_objects)[obj_idx]->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1");
|
||||
|
||||
ModelObject* object = (*m_objects)[obj_idx];
|
||||
if (object->volumes.size() <= 1)
|
||||
return items;
|
||||
wxDataViewItemArray items = add_volumes_to_object_in_list(obj_idx, std::move(add_to_selection));
|
||||
|
||||
object->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1");
|
||||
changed_object(int(obj_idx));
|
||||
|
||||
wxDataViewItem object_item = m_objects_model->GetItemById(obj_idx);
|
||||
m_objects_model->DeleteVolumeChildren(object_item);
|
||||
|
||||
for (const ModelVolume* volume : object->volumes) {
|
||||
wxDataViewItem vol_item = m_objects_model->AddVolumeChild(object_item, from_u8(volume->name),
|
||||
volume->type(),
|
||||
get_warning_icon_name(volume->mesh().stats()),
|
||||
volume->config.has("extruder") ? volume->config.extruder() : 0,
|
||||
false);
|
||||
// add settings to the part, if it has those
|
||||
add_settings_item(vol_item, &volume->config.get());
|
||||
|
||||
if (add_to_selection && add_to_selection(volume))
|
||||
items.Add(vol_item);
|
||||
}
|
||||
|
||||
changed_object(obj_idx);
|
||||
return items;
|
||||
}
|
||||
|
||||
|
|
|
@ -343,6 +343,8 @@ public:
|
|||
void init_objects();
|
||||
bool multiple_selection() const ;
|
||||
bool is_selected(const ItemType type) const;
|
||||
bool is_connectors_item_selected() const;
|
||||
bool is_connectors_item_selected(const wxDataViewItemArray& sels) const;
|
||||
int get_selected_layers_range_idx() const;
|
||||
void set_selected_layers_range_idx(const int range_idx) { m_selected_layers_range_idx = range_idx; }
|
||||
void set_selection_mode(SELECTION_MODE mode) { m_selection_mode = mode; }
|
||||
|
|
|
@ -763,7 +763,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||
#endif // ENABLE_WORLD_COORDINATE
|
||||
m_new_enabled = true;
|
||||
}
|
||||
else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) {
|
||||
else if (obj_list->is_connectors_item_selected() || obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) {
|
||||
reset_settings_value();
|
||||
m_new_move_label_string = L("Translate");
|
||||
m_new_rotate_label_string = L("Rotate");
|
||||
|
|
|
@ -597,114 +597,109 @@ static float get_grabber_mean_size(const BoundingBoxf3& bb)
|
|||
return float((bb.size().x() + bb.size().y() + bb.size().z()) / 3.0);
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::render_cut_center_grabber()
|
||||
void GLGizmoCut3D::render_model(GLModel& model, const ColorRGBA& color, Transform3d view_model_matrix)
|
||||
{
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
if (shader) {
|
||||
shader->start_using();
|
||||
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
shader->set_uniform("projection_matrix", wxGetApp().plater()->get_camera().get_projection_matrix());
|
||||
|
||||
model.set_color(color);
|
||||
model.render();
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::render_line(GLModel& line_model, const ColorRGBA& color, Transform3d view_model_matrix, float width)
|
||||
{
|
||||
GLShaderProgram* shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
|
||||
if (shader) {
|
||||
shader->start_using();
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
shader->set_uniform("projection_matrix", wxGetApp().plater()->get_camera().get_projection_matrix());
|
||||
shader->set_uniform("width", width);
|
||||
|
||||
line_model.set_color(color);
|
||||
line_model.render();
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::render_rotation_snapping(Axis axis, const ColorRGBA& color)
|
||||
{
|
||||
GLShaderProgram* line_shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
|
||||
if (!line_shader)
|
||||
return;
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
Transform3d view_model_matrix = camera.get_view_matrix() * translation_transform(m_plane_center) * m_start_dragging_m;
|
||||
|
||||
if (axis == X)
|
||||
view_model_matrix = view_model_matrix * rotation_transform(0.5 * PI * Vec3d::UnitY()) * rotation_transform(-PI * Vec3d::UnitZ());
|
||||
else
|
||||
view_model_matrix = view_model_matrix * rotation_transform(-0.5 * PI * Vec3d::UnitZ()) * rotation_transform(-0.5 * PI * Vec3d::UnitY());
|
||||
|
||||
line_shader->start_using();
|
||||
line_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
line_shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
line_shader->set_uniform("width", 0.25f);
|
||||
|
||||
m_circle.render();
|
||||
m_scale.render();
|
||||
m_snap_radii.render();
|
||||
m_reference_radius.render();
|
||||
if (m_dragging) {
|
||||
line_shader->set_uniform("width", 1.5f);
|
||||
m_angle_arc.set_color(color);
|
||||
m_angle_arc.render();
|
||||
}
|
||||
|
||||
line_shader->stop_using();
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::render_grabber_connection(const ColorRGBA& color, Transform3d view_matrix)
|
||||
{
|
||||
const Transform3d line_view_matrix = view_matrix * scale_transform(Vec3d(1.0, 1.0, m_grabber_connection_len));
|
||||
|
||||
render_line(m_grabber_connection, color, line_view_matrix, 0.2f);
|
||||
};
|
||||
|
||||
void GLGizmoCut3D::render_cut_plane_grabbers()
|
||||
{
|
||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
if (!shader)
|
||||
return;
|
||||
|
||||
ColorRGBA color = m_hover_id == Z ? complementary(GRABBER_COLOR) : GRABBER_COLOR;
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Transform3d view_matrix = wxGetApp().plater()->get_camera().get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m;
|
||||
|
||||
const Grabber& grabber = m_grabbers.front();
|
||||
const float mean_size = get_grabber_mean_size(bounding_box());
|
||||
|
||||
const BoundingBoxf3 box = bounding_box();
|
||||
|
||||
const float mean_size = get_grabber_mean_size(box);
|
||||
double size = m_dragging && m_hover_id == Z ? double(grabber.get_dragging_half_size(mean_size)) : double(grabber.get_half_size(mean_size));
|
||||
|
||||
Vec3d cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
|
||||
Vec3d offset = 1.25 * size * Vec3d::UnitZ();
|
||||
|
||||
shader->start_using();
|
||||
shader->set_uniform("emission_factor", 0.1f);
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
|
||||
const Transform3d view_matrix = camera.get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m;
|
||||
|
||||
auto render = [shader, this](GLModel& model, const ColorRGBA& color, Transform3d view_model_matrix) {
|
||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
|
||||
model.set_color(color);
|
||||
model.render();
|
||||
};
|
||||
|
||||
auto render_grabber_connection = [shader, camera, view_matrix, this](const ColorRGBA& color)
|
||||
{
|
||||
shader->stop_using();
|
||||
GLShaderProgram* line_shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
|
||||
if (!line_shader)
|
||||
return;
|
||||
|
||||
line_shader->start_using();
|
||||
line_shader->set_uniform("emission_factor", 0.1f);
|
||||
line_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
|
||||
const Transform3d trafo = view_matrix * scale_transform(Vec3d(1.0, 1.0, m_grabber_connection_len));
|
||||
line_shader->set_uniform("view_model_matrix", trafo);
|
||||
line_shader->set_uniform("normal_matrix", (Matrix3d)trafo.matrix().block(0, 0, 3, 3).inverse().transpose());
|
||||
line_shader->set_uniform("width", 0.2f);
|
||||
|
||||
m_grabber_connection.set_color(color);
|
||||
m_grabber_connection.render();
|
||||
|
||||
line_shader->stop_using();
|
||||
shader->start_using();
|
||||
};
|
||||
|
||||
auto render_rotation_snapping = [shader, camera, this](Axis axis, const ColorRGBA& color)
|
||||
{
|
||||
Transform3d view_model_matrix = camera.get_view_matrix() * translation_transform(m_plane_center) * m_start_dragging_m;
|
||||
|
||||
if (axis == X)
|
||||
view_model_matrix = view_model_matrix * rotation_transform( 0.5 * PI * Vec3d::UnitY()) * rotation_transform(-PI * Vec3d::UnitZ());
|
||||
else
|
||||
view_model_matrix = view_model_matrix * rotation_transform(-0.5 * PI * Vec3d::UnitZ()) * rotation_transform(-0.5 * PI * Vec3d::UnitY());
|
||||
|
||||
shader->stop_using();
|
||||
|
||||
GLShaderProgram* line_shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
|
||||
if (!line_shader)
|
||||
return;
|
||||
|
||||
line_shader->start_using();
|
||||
line_shader->set_uniform("emission_factor", 0.1f);
|
||||
line_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
|
||||
line_shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
line_shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
|
||||
line_shader->set_uniform("width", 0.25f);
|
||||
|
||||
m_circle.render();
|
||||
m_scale.render();
|
||||
m_snap_radii.render();
|
||||
m_reference_radius.render();
|
||||
if (m_dragging) {
|
||||
line_shader->set_uniform("width", 1.5f);
|
||||
m_angle_arc.set_color(color);
|
||||
m_angle_arc.render();
|
||||
}
|
||||
|
||||
line_shader->stop_using();
|
||||
shader->start_using();
|
||||
};
|
||||
|
||||
// render Z grabber
|
||||
|
||||
if ((!m_dragging && m_hover_id < 0))
|
||||
render_grabber_connection(color);
|
||||
render(m_sphere.model, color, view_matrix * scale_transform(size));
|
||||
render_grabber_connection(color, view_matrix);
|
||||
render_model(m_sphere.model, color, view_matrix * scale_transform(size));
|
||||
|
||||
if (!m_dragging && m_hover_id < 0 || m_hover_id == Z)
|
||||
{
|
||||
const BoundingBoxf3 tbb = transformed_bounding_box();
|
||||
if (tbb.min.z() <= 0.0)
|
||||
render(m_cone.model, color, view_matrix * assemble_transform(-offset, PI * Vec3d::UnitX(), cone_scale));
|
||||
render_model(m_cone.model, color, view_matrix * assemble_transform(-offset, PI * Vec3d::UnitX(), cone_scale));
|
||||
|
||||
if (tbb.max.z() >= 0.0)
|
||||
render(m_cone.model, color, view_matrix * assemble_transform(offset, Vec3d::Zero(), cone_scale));
|
||||
render_model(m_cone.model, color, view_matrix * assemble_transform(offset, Vec3d::Zero(), cone_scale));
|
||||
}
|
||||
|
||||
// render top sphere for X/Y grabbers
|
||||
|
@ -714,7 +709,7 @@ void GLGizmoCut3D::render_cut_center_grabber()
|
|||
size = m_dragging ? double(grabber.get_dragging_half_size(mean_size)) : double(grabber.get_half_size(mean_size));
|
||||
color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) :
|
||||
m_hover_id == X ? complementary(ColorRGBA::RED()) : ColorRGBA::GRAY();
|
||||
render(m_sphere.model, color, view_matrix * assemble_transform(m_grabber_connection_len * Vec3d::UnitZ(), Vec3d::Zero(), size * Vec3d::Ones()));
|
||||
render_model(m_sphere.model, color, view_matrix * assemble_transform(m_grabber_connection_len * Vec3d::UnitZ(), Vec3d::Zero(), size * Vec3d::Ones()));
|
||||
}
|
||||
|
||||
// render X grabber
|
||||
|
@ -726,14 +721,14 @@ void GLGizmoCut3D::render_cut_center_grabber()
|
|||
color = m_hover_id == X ? complementary(ColorRGBA::RED()) : ColorRGBA::RED();
|
||||
|
||||
if (m_hover_id == X) {
|
||||
render_grabber_connection(color);
|
||||
render_grabber_connection(color, view_matrix);
|
||||
render_rotation_snapping(X, color);
|
||||
}
|
||||
|
||||
offset = Vec3d(0.0, 1.25 * size, m_grabber_connection_len);
|
||||
render(m_cone.model, color, view_matrix * assemble_transform(offset, -0.5 * PI * Vec3d::UnitX(), cone_scale));
|
||||
render_model(m_cone.model, color, view_matrix * assemble_transform(offset, -0.5 * PI * Vec3d::UnitX(), cone_scale));
|
||||
offset = Vec3d(0.0, -1.25 * size, m_grabber_connection_len);
|
||||
render(m_cone.model, color, view_matrix * assemble_transform(offset, 0.5 * PI * Vec3d::UnitX(), cone_scale));
|
||||
render_model(m_cone.model, color, view_matrix * assemble_transform(offset, 0.5 * PI * Vec3d::UnitX(), cone_scale));
|
||||
}
|
||||
|
||||
// render Y grabber
|
||||
|
@ -745,17 +740,15 @@ void GLGizmoCut3D::render_cut_center_grabber()
|
|||
color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) : ColorRGBA::GREEN();
|
||||
|
||||
if (m_hover_id == Y) {
|
||||
render_grabber_connection(color);
|
||||
render_grabber_connection(color, view_matrix);
|
||||
render_rotation_snapping(Y, color);
|
||||
}
|
||||
|
||||
offset = Vec3d(1.25 * size, 0.0, m_grabber_connection_len);
|
||||
render(m_cone.model, color, view_matrix * assemble_transform(offset, 0.5 * PI * Vec3d::UnitY(), cone_scale));
|
||||
render_model(m_cone.model, color, view_matrix * assemble_transform(offset, 0.5 * PI * Vec3d::UnitY(), cone_scale));
|
||||
offset = Vec3d(-1.25 * size, 0.0, m_grabber_connection_len);
|
||||
render(m_cone.model, color, view_matrix * assemble_transform(offset, -0.5 * PI * Vec3d::UnitY(), cone_scale));
|
||||
render_model(m_cone.model, color, view_matrix * assemble_transform(offset, -0.5 * PI * Vec3d::UnitY(), cone_scale));
|
||||
}
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
|
||||
void GLGizmoCut3D::render_cut_line()
|
||||
|
@ -766,23 +759,10 @@ void GLGizmoCut3D::render_cut_line()
|
|||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
GLShaderProgram* shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
|
||||
if (shader != nullptr) {
|
||||
shader->start_using();
|
||||
m_cut_line.reset();
|
||||
m_cut_line.init_from(its_make_line((Vec3f)m_line_beg.cast<float>(), (Vec3f)m_line_end.cast<float>()));
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
shader->set_uniform("width", 0.25f);
|
||||
|
||||
m_cut_line.reset();
|
||||
m_cut_line.init_from(its_make_line((Vec3f)m_line_beg.cast<float>(), (Vec3f)m_line_end.cast<float>()));
|
||||
|
||||
m_cut_line.set_color(GRABBER_COLOR);
|
||||
m_cut_line.render();
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
render_line(m_cut_line, GRABBER_COLOR, wxGetApp().plater()->get_camera().get_view_matrix(), 0.25f);
|
||||
}
|
||||
|
||||
bool GLGizmoCut3D::on_init()
|
||||
|
@ -1303,7 +1283,7 @@ void GLGizmoCut3D::on_render()
|
|||
|
||||
if (!m_hide_cut_plane && !m_connectors_editing) {
|
||||
render_cut_plane();
|
||||
render_cut_center_grabber();
|
||||
render_cut_plane_grabbers();
|
||||
}
|
||||
|
||||
render_cut_line();
|
||||
|
|
|
@ -221,7 +221,11 @@ private:
|
|||
void discard_cut_line_processing();
|
||||
|
||||
void render_cut_plane();
|
||||
void render_cut_center_grabber();
|
||||
void render_model(GLModel& model, const ColorRGBA& color, Transform3d view_model_matrix);
|
||||
void render_line(GLModel& line_model, const ColorRGBA& color, Transform3d view_model_matrix, float width);
|
||||
void render_rotation_snapping(Axis axis, const ColorRGBA& color);
|
||||
void render_grabber_connection(const ColorRGBA& color, Transform3d view_matrix);
|
||||
void render_cut_plane_grabbers();
|
||||
void render_cut_line();
|
||||
void perform_cut(const Selection&selection);
|
||||
void set_center_pos(const Vec3d¢er_pos, bool force = false);
|
||||
|
|
|
@ -81,12 +81,7 @@ std::string GLGizmoMove3D::on_get_name() const
|
|||
bool GLGizmoMove3D::on_is_activable() const
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
if (selection.is_any_volume() || selection.is_any_modifier()) {
|
||||
if (int obj_idx = selection.get_object_idx(); obj_idx >= 0)
|
||||
return !m_parent.get_model()->objects[obj_idx]->is_cut();
|
||||
}
|
||||
|
||||
return !selection.is_empty();
|
||||
return !selection.is_any_cut_volume() && !selection.is_any_connector() && !selection.is_empty();
|
||||
}
|
||||
|
||||
void GLGizmoMove3D::on_start_dragging()
|
||||
|
|
|
@ -869,12 +869,7 @@ std::string GLGizmoRotate3D::on_get_name() const
|
|||
bool GLGizmoRotate3D::on_is_activable() const
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
if (selection.is_any_volume() || selection.is_any_modifier()) {
|
||||
if (int obj_idx = selection.get_object_idx(); obj_idx >= 0)
|
||||
return !m_parent.get_model()->objects[obj_idx]->is_cut();
|
||||
}
|
||||
|
||||
return !selection.is_empty();
|
||||
return !selection.is_any_cut_volume() && !selection.is_any_connector() && !selection.is_empty();
|
||||
}
|
||||
|
||||
void GLGizmoRotate3D::on_start_dragging()
|
||||
|
|
|
@ -168,12 +168,7 @@ std::string GLGizmoScale3D::on_get_name() const
|
|||
bool GLGizmoScale3D::on_is_activable() const
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
if (selection.is_any_volume() || selection.is_any_modifier()) {
|
||||
if (int obj_idx = selection.get_object_idx(); obj_idx >= 0)
|
||||
return !m_parent.get_model()->objects[obj_idx]->is_cut();
|
||||
}
|
||||
|
||||
return !selection.is_empty() && !selection.is_wipe_tower();
|
||||
return !selection.is_any_cut_volume() && !selection.is_any_connector() && !selection.is_empty() && !selection.is_wipe_tower();
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::on_start_dragging()
|
||||
|
@ -460,7 +455,7 @@ void GLGizmoScale3D::on_render()
|
|||
// draw grabbers
|
||||
render_grabbers(grabber_mean_size);
|
||||
}
|
||||
else if (m_hover_id == 0 || m_hover_id == 1) {
|
||||
else if ((m_hover_id == 0 || m_hover_id == 1) && m_grabbers[0].enabled && m_grabbers[1].enabled) {
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// draw connections
|
||||
#if ENABLE_GL_CORE_PROFILE
|
||||
|
@ -505,7 +500,7 @@ void GLGizmoScale3D::on_render()
|
|||
shader->stop_using();
|
||||
}
|
||||
}
|
||||
else if (m_hover_id == 2 || m_hover_id == 3) {
|
||||
else if ((m_hover_id == 2 || m_hover_id == 3) && m_grabbers[2].enabled && m_grabbers[3].enabled) {
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// draw connections
|
||||
#if ENABLE_GL_CORE_PROFILE
|
||||
|
@ -550,7 +545,7 @@ void GLGizmoScale3D::on_render()
|
|||
shader->stop_using();
|
||||
}
|
||||
}
|
||||
else if (m_hover_id == 4 || m_hover_id == 5) {
|
||||
else if ((m_hover_id == 4 || m_hover_id == 5) && m_grabbers[4].enabled && m_grabbers[5].enabled) {
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// draw connections
|
||||
#if ENABLE_GL_CORE_PROFILE
|
||||
|
|
|
@ -510,6 +510,28 @@ void Selection::volumes_changed(const std::vector<size_t> &map_volume_old_to_new
|
|||
this->set_bounding_boxes_dirty();
|
||||
}
|
||||
|
||||
bool Selection::is_any_connector() const
|
||||
{
|
||||
const int obj_idx = get_object_idx();
|
||||
|
||||
if ((is_any_volume() || is_any_modifier() || is_mixed()) && // some solid_part AND/OR modifier is selected
|
||||
obj_idx >= 0 && m_model->objects[obj_idx]->is_cut()) {
|
||||
const ModelVolumePtrs& obj_volumes = m_model->objects[obj_idx]->volumes;
|
||||
for (size_t vol_idx = 0; vol_idx < obj_volumes.size(); vol_idx++)
|
||||
if (obj_volumes[vol_idx]->is_cut_connector())
|
||||
for (const GLVolume* v : *m_volumes)
|
||||
if (v->object_idx() == obj_idx && v->volume_idx() == (int)vol_idx && v->selected)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Selection::is_any_cut_volume() const
|
||||
{
|
||||
const int obj_idx = get_object_idx();
|
||||
return is_any_volume() && obj_idx >= 0 && m_model->objects[obj_idx]->is_cut();
|
||||
}
|
||||
|
||||
bool Selection::is_single_full_instance() const
|
||||
{
|
||||
if (m_type == SingleFullInstance)
|
||||
|
|
|
@ -320,6 +320,8 @@ public:
|
|||
bool is_single_volume() const { return m_type == SingleVolume; }
|
||||
bool is_multiple_volume() const { return m_type == MultipleVolume; }
|
||||
bool is_any_volume() const { return is_single_volume() || is_multiple_volume(); }
|
||||
bool is_any_connector() const;
|
||||
bool is_any_cut_volume() const;
|
||||
bool is_mixed() const { return m_type == Mixed; }
|
||||
bool is_from_single_instance() const { return get_instance_idx() != -1; }
|
||||
bool is_from_single_object() const;
|
||||
|
|
Loading…
Reference in a new issue