diff --git a/resources/shaders/110/gouraud.fs b/resources/shaders/110/gouraud.fs index fce2a6f39f..6f354ff9a6 100644 --- a/resources/shaders/110/gouraud.fs +++ b/resources/shaders/110/gouraud.fs @@ -29,6 +29,9 @@ struct SlopeDetection }; uniform vec4 uniform_color; +uniform bool use_color_clip_plane; +uniform vec4 uniform_color_clip_plane_1; +uniform vec4 uniform_color_clip_plane_2; uniform SlopeDetection slope; //BBS: add outline_color @@ -42,6 +45,7 @@ uniform bool is_outline; uniform PrintVolumeDetection print_volume; varying vec3 clipping_planes_dots; +varying float color_clip_plane_dot; // x = diffuse, y = specular; varying vec2 intensity; @@ -54,45 +58,50 @@ void main() { if (any(lessThan(clipping_planes_dots, ZERO))) discard; - vec3 color = uniform_color.rgb; - float alpha = uniform_color.a; + + vec4 color; + if (use_color_clip_plane) { + color.rgb = (color_clip_plane_dot < 0.0) ? uniform_color_clip_plane_1.rgb : uniform_color_clip_plane_2.rgb; + color.a = uniform_color.a; + } + else + color = uniform_color; if (slope.actived) { if(world_pos.z<0.1&&world_pos.z>-0.1) { - color = LightBlue; - alpha = 0.8; + color.rgb = LightBlue; + color.a = 0.8; } else if( world_normal_z < slope.normal_z - EPSILON) { - color = color * 0.5 + LightRed * 0.5; - alpha = 0.8; + color.rgb = color.rgb * 0.5 + LightRed * 0.5; + color.a = 0.8; } } - // if the fragment is outside the print volume -> use darker color - vec3 pv_check_min = ZERO; - vec3 pv_check_max = ZERO; + // if the fragment is outside the print volume -> use darker color + vec3 pv_check_min = ZERO; + vec3 pv_check_max = ZERO; if (print_volume.type == 0) { - // rectangle - pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x); - pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y); - color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color; - } - else if (print_volume.type == 1) { - // circle - float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy); - pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x); - pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y); - color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color; - } - - //BBS: add outline_color - if (is_outline) - gl_FragColor = uniform_color; + // rectangle + pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x); + pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y); + } + else if (print_volume.type == 1) { + // circle + float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy); + pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x); + pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y); + } + color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb; + + //BBS: add outline_color + if (is_outline) + gl_FragColor = uniform_color; #ifdef ENABLE_ENVIRONMENT_MAP else if (use_environment_tex) - gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha); + gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a); #endif - else - gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); + else + gl_FragColor = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a); } \ No newline at end of file diff --git a/resources/shaders/110/gouraud.vs b/resources/shaders/110/gouraud.vs index 0e8562871b..ff3a190c79 100644 --- a/resources/shaders/110/gouraud.vs +++ b/resources/shaders/110/gouraud.vs @@ -35,6 +35,8 @@ uniform SlopeDetection slope; uniform vec2 z_range; // Clipping plane - general orientation. Used by the SLA gizmo. uniform vec4 clipping_plane; +// Color clip plane - general orientation. Used by the cut gizmo. +uniform vec4 color_clip_plane; attribute vec3 v_position; attribute vec3 v_normal; @@ -43,6 +45,7 @@ attribute vec3 v_normal; varying vec2 intensity; varying vec3 clipping_planes_dots; +varying float color_clip_plane_dot; varying vec4 world_pos; varying float world_normal_z; @@ -74,4 +77,5 @@ void main() gl_Position = projection_matrix * position; // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); + color_clip_plane_dot = dot(world_pos, color_clip_plane); } diff --git a/resources/shaders/140/gouraud.fs b/resources/shaders/140/gouraud.fs index bff8434aa9..84bce5c035 100644 --- a/resources/shaders/140/gouraud.fs +++ b/resources/shaders/140/gouraud.fs @@ -29,6 +29,9 @@ struct SlopeDetection }; uniform vec4 uniform_color; +uniform bool use_color_clip_plane; +uniform vec4 uniform_color_clip_plane_1; +uniform vec4 uniform_color_clip_plane_2; uniform SlopeDetection slope; //BBS: add outline_color @@ -42,6 +45,7 @@ uniform bool is_outline; uniform PrintVolumeDetection print_volume; in vec3 clipping_planes_dots; +in float color_clip_plane_dot; // x = diffuse, y = specular; in vec2 intensity; @@ -50,49 +54,56 @@ in vec4 world_pos; in float world_normal_z; in vec3 eye_normal; +out vec4 out_color; + void main() { if (any(lessThan(clipping_planes_dots, ZERO))) discard; - vec3 color = uniform_color.rgb; - float alpha = uniform_color.a; + + vec4 color; + if (use_color_clip_plane) { + color.rgb = (color_clip_plane_dot < 0.0) ? uniform_color_clip_plane_1.rgb : uniform_color_clip_plane_2.rgb; + color.a = uniform_color.a; + } + else + color = uniform_color; if (slope.actived) { if(world_pos.z<0.1&&world_pos.z>-0.1) { - color = LightBlue; - alpha = 0.8; + color.rgb = LightBlue; + color.a = 0.8; } else if( world_normal_z < slope.normal_z - EPSILON) { - color = color * 0.5 + LightRed * 0.5; - alpha = 0.8; + color.rgb = color.rgb * 0.5 + LightRed * 0.5; + color.a = 0.8; } } - // if the fragment is outside the print volume -> use darker color - vec3 pv_check_min = ZERO; - vec3 pv_check_max = ZERO; + // if the fragment is outside the print volume -> use darker color + vec3 pv_check_min = ZERO; + vec3 pv_check_max = ZERO; if (print_volume.type == 0) { - // rectangle - pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x); - pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y); - color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color; - } - else if (print_volume.type == 1) { - // circle - float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy); - pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x); - pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y); - color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color; - } - - //BBS: add outline_color - if (is_outline) - gl_FragColor = uniform_color; + // rectangle + pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x); + pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y); + } + else if (print_volume.type == 1) { + // circle + float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy); + pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x); + pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y); + } + color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb; + + //BBS: add outline_color + if (is_outline) + out_color = uniform_color; #ifdef ENABLE_ENVIRONMENT_MAP else if (use_environment_tex) - gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha); + out_color = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a); #endif - else - gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); + else + out_color = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a); } \ No newline at end of file diff --git a/resources/shaders/140/gouraud.vs b/resources/shaders/140/gouraud.vs index 8e657205fb..72dd4ff1bf 100644 --- a/resources/shaders/140/gouraud.vs +++ b/resources/shaders/140/gouraud.vs @@ -35,6 +35,8 @@ uniform SlopeDetection slope; uniform vec2 z_range; // Clipping plane - general orientation. Used by the SLA gizmo. uniform vec4 clipping_plane; +// Color clip plane - general orientation. Used by the cut gizmo. +uniform vec4 color_clip_plane; in vec3 v_position; in vec3 v_normal; @@ -43,6 +45,7 @@ in vec3 v_normal; out vec2 intensity; out vec3 clipping_planes_dots; +out float color_clip_plane_dot; out vec4 world_pos; out float world_normal_z; @@ -74,4 +77,5 @@ void main() gl_Position = projection_matrix * position; // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); + color_clip_plane_dot = dot(world_pos, color_clip_plane); } diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 3b735d8275..7325941ed0 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -1,3 +1,14 @@ +///|/ Copyright (c) Prusa Research 2016 - 2023 Lukáš Matěna @lukasmatena, Enrico Turri @enricoturri1966, Oleksandra Iushchenko @YuSanka, Tomáš Mészáros @tamasmeszaros, Vojtěch Bubník @bubnikv, Filip Sykala @Jony01, Lukáš Hejl @hejllukas, David Kocík @kocikdav, Vojtěch Král @vojtechkral +///|/ Copyright (c) 2017 Eyal Soha @eyal0 +///|/ Copyright (c) Slic3r 2015 Alessandro Ranellucci @alranel +///|/ +///|/ ported from lib/Slic3r/GUI/3DScene.pm: +///|/ Copyright (c) Prusa Research 2016 - 2019 Vojtěch Bubník @bubnikv, Enrico Turri @enricoturri1966, Oleksandra Iushchenko @YuSanka +///|/ Copyright (c) Slic3r 2013 - 2016 Alessandro Ranellucci @alranel +///|/ Copyright (c) 2013 Guillaume Seguin @iXce +///|/ +///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher +///|/ #include #include "3DScene.hpp" @@ -869,6 +880,10 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab shader->set_uniform("uniform_color", volume.first->render_color); shader->set_uniform("z_range", m_z_range); shader->set_uniform("clipping_plane", m_clipping_plane); + shader->set_uniform("use_color_clip_plane", m_use_color_clip_plane); + shader->set_uniform("color_clip_plane", m_color_clip_plane); + shader->set_uniform("uniform_color_clip_plane_1", m_color_clip_plane_colors[0]); + shader->set_uniform("uniform_color_clip_plane_2", m_color_clip_plane_colors[1]); //BOOST_LOG_TRIVIAL(info) << boost::format("set uniform_color to {%1%, %2%, %3%, %4%}, with_outline=%5%, selected %6%") // %volume.first->render_color[0]%volume.first->render_color[1]%volume.first->render_color[2]%volume.first->render_color[3] // %with_outline%volume.first->selected; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index dcf2713fb5..0a0f631644 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1341,21 +1341,31 @@ ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state() const void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo, int instance_idx) { + if (current_printer_technology() != ptSLA) + return; + m_render_sla_auxiliaries = visible; + std::vector>* raycasters = get_raycasters_for_picking(SceneRaycaster::EType::Volume); + for (GLVolume* vol : m_volumes.volumes) { if (vol->composite_id.object_id >= 1000 && vol->composite_id.object_id < 1000 + wxGetApp().plater()->get_partplate_list().get_plate_count()) continue; // the wipe tower - if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo) - && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx) - && vol->composite_id.volume_id < 0) + if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo) + && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx) + && vol->composite_id.volume_id < 0) { vol->is_active = visible; + auto it = std::find_if(raycasters->begin(), raycasters->end(), [vol](std::shared_ptr item) { return item->get_raycaster() == vol->mesh_raycaster.get(); }); + if (it != raycasters->end()) + (*it)->set_active(vol->is_active); + } } } void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject* mo, int instance_idx, const ModelVolume* mv) { + std::vector>* raycasters = get_raycasters_for_picking(SceneRaycaster::EType::Volume); for (GLVolume* vol : m_volumes.volumes) { // BBS: add partplate logic if (vol->composite_id.object_id >= 1000 && @@ -1367,6 +1377,8 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx) && (mv == nullptr || m_model->objects[vol->composite_id.object_id]->volumes[vol->composite_id.volume_id] == mv)) { vol->is_active = visible; + if (!vol->is_modifier) + vol->color.a(1.f); if (instance_idx == -1) { vol->force_native_color = false; @@ -1374,10 +1386,12 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject } else { const GLGizmosManager& gm = get_gizmos_manager(); auto gizmo_type = gm.get_current_type(); - if ( (gizmo_type == GLGizmosManager::FdmSupports - || gizmo_type == GLGizmosManager::Seam) - && ! vol->is_modifier) + if ( (gizmo_type == GLGizmosManager::FdmSupports + || gizmo_type == GLGizmosManager::Seam + || gizmo_type == GLGizmosManager::Cut) + && !vol->is_modifier) { vol->force_neutral_color = true; + } else if (gizmo_type == GLGizmosManager::MmuSegmentation) vol->is_active = false; else @@ -1385,7 +1399,12 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject } } } + + auto it = std::find_if(raycasters->begin(), raycasters->end(), [vol](std::shared_ptr item) { return item->get_raycaster() == vol->mesh_raycaster.get(); }); + if (it != raycasters->end()) + (*it)->set_active(vol->is_active); } + if (visible && !mo) toggle_sla_auxiliaries_visibility(true, mo, instance_idx); @@ -4003,6 +4022,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (/*m_gizmos.get_current_type() != GLGizmosManager::SlaSupports &&*/ m_gizmos.get_current_type() != GLGizmosManager::FdmSupports && m_gizmos.get_current_type() != GLGizmosManager::Seam + && m_gizmos.get_current_type() != GLGizmosManager::Cut && m_gizmos.get_current_type() != GLGizmosManager::MmuSegmentation) { m_rectangle_selection.start_dragging(m_mouse.position, evt.ShiftDown() ? GLSelectionRectangle::Select : GLSelectionRectangle::Deselect); m_dirty = true; @@ -4052,7 +4072,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) int volume_idx = get_first_hover_volume_idx(); BoundingBoxf3 volume_bbox = m_volumes.volumes[volume_idx]->transformed_bounding_box(); volume_bbox.offset(1.0); - if ((!any_gizmo_active || !evt.CmdDown()) && volume_bbox.contains(m_mouse.scene_position)) { + const bool is_cut_connector_selected = m_selection.is_any_connector(); + if ((!any_gizmo_active || !evt.CmdDown()) && volume_bbox.contains(m_mouse.scene_position) && !is_cut_connector_selected) { m_volumes.volumes[volume_idx]->hover = GLVolume::HS_None; // The dragging operation is initiated. m_mouse.drag.move_volume_idx = volume_idx; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 05bb7cdcc2..9e385ab54c 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -644,6 +644,28 @@ void Selection::volumes_changed(const std::vector &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) diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 594c799607..e130cb18be 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -249,6 +249,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;