This commit is contained in:
bubnikv 2019-03-20 10:34:10 +01:00
commit 001d0c0fe9
29 changed files with 2526 additions and 2416 deletions

View File

@ -33,8 +33,6 @@
// Changed algorithm to extract euler angles from rotation matrix // Changed algorithm to extract euler angles from rotation matrix
#define ENABLE_NEW_EULER_ANGLES (1 && ENABLE_1_42_0_ALPHA4) #define ENABLE_NEW_EULER_ANGLES (1 && ENABLE_1_42_0_ALPHA4)
// Added minimum threshold for click and drag movements
#define ENABLE_MOVE_MIN_THRESHOLD (1 && ENABLE_1_42_0_ALPHA4)
// Modified initial default placement of generic subparts // Modified initial default placement of generic subparts
#define ENABLE_GENERIC_SUBPARTS_PLACEMENT (1 && ENABLE_1_42_0_ALPHA4) #define ENABLE_GENERIC_SUBPARTS_PLACEMENT (1 && ENABLE_1_42_0_ALPHA4)
// Bunch of fixes related to volumes centering // Bunch of fixes related to volumes centering
@ -58,4 +56,5 @@
// Toolbars and Gizmos use icons imported from svg files // Toolbars and Gizmos use icons imported from svg files
#define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG) #define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG)
#endif // _technologies_h_ #endif // _technologies_h_

View File

@ -28,6 +28,8 @@ set(SLIC3R_GUI_SOURCES
GUI/GLCanvas3D.cpp GUI/GLCanvas3D.cpp
GUI/GLCanvas3DManager.hpp GUI/GLCanvas3DManager.hpp
GUI/GLCanvas3DManager.cpp GUI/GLCanvas3DManager.cpp
GUI/Selection.hpp
GUI/Selection.cpp
GUI/Gizmos/GLGizmoBase.cpp GUI/Gizmos/GLGizmoBase.cpp
GUI/Gizmos/GLGizmoBase.hpp GUI/Gizmos/GLGizmoBase.hpp
GUI/Gizmos/GLGizmoMove.cpp GUI/Gizmos/GLGizmoMove.cpp

File diff suppressed because it is too large Load Diff

View File

@ -4,12 +4,12 @@
#include <stddef.h> #include <stddef.h>
#include <memory> #include <memory>
#include "libslic3r/Technologies.hpp"
#include "3DScene.hpp" #include "3DScene.hpp"
#include "GLToolbar.hpp" #include "GLToolbar.hpp"
#include "Event.hpp" #include "Event.hpp"
#include "3DBed.hpp" #include "3DBed.hpp"
#include "Camera.hpp" #include "Camera.hpp"
#include "Selection.hpp"
#include <float.h> #include <float.h>
@ -297,24 +297,19 @@ class GLCanvas3D
{ {
static const Point Invalid_2D_Point; static const Point Invalid_2D_Point;
static const Vec3d Invalid_3D_Point; static const Vec3d Invalid_3D_Point;
#if ENABLE_MOVE_MIN_THRESHOLD
static const int MoveThresholdPx; static const int MoveThresholdPx;
#endif // ENABLE_MOVE_MIN_THRESHOLD
Point start_position_2D; Point start_position_2D;
Vec3d start_position_3D; Vec3d start_position_3D;
int move_volume_idx; int move_volume_idx;
#if ENABLE_MOVE_MIN_THRESHOLD
bool move_requires_threshold; bool move_requires_threshold;
Point move_start_threshold_position_2D; Point move_start_threshold_position_2D;
#endif // ENABLE_MOVE_MIN_THRESHOLD
public: public:
Drag(); Drag();
}; };
bool dragging; bool dragging;
bool left_down;
Vec2d position; Vec2d position;
Vec3d scene_position; Vec3d scene_position;
Drag drag; Drag drag;
@ -324,309 +319,18 @@ class GLCanvas3D
void set_start_position_2D_as_invalid() { drag.start_position_2D = Drag::Invalid_2D_Point; } void set_start_position_2D_as_invalid() { drag.start_position_2D = Drag::Invalid_2D_Point; }
void set_start_position_3D_as_invalid() { drag.start_position_3D = Drag::Invalid_3D_Point; } void set_start_position_3D_as_invalid() { drag.start_position_3D = Drag::Invalid_3D_Point; }
#if ENABLE_MOVE_MIN_THRESHOLD
void set_move_start_threshold_position_2D_as_invalid() { drag.move_start_threshold_position_2D = Drag::Invalid_2D_Point; } void set_move_start_threshold_position_2D_as_invalid() { drag.move_start_threshold_position_2D = Drag::Invalid_2D_Point; }
#endif // ENABLE_MOVE_MIN_THRESHOLD
bool is_start_position_2D_defined() const { return (drag.start_position_2D != Drag::Invalid_2D_Point); } bool is_start_position_2D_defined() const { return (drag.start_position_2D != Drag::Invalid_2D_Point); }
bool is_start_position_3D_defined() const { return (drag.start_position_3D != Drag::Invalid_3D_Point); } bool is_start_position_3D_defined() const { return (drag.start_position_3D != Drag::Invalid_3D_Point); }
#if ENABLE_MOVE_MIN_THRESHOLD
bool is_move_start_threshold_position_2D_defined() const { return (drag.move_start_threshold_position_2D != Drag::Invalid_2D_Point); } bool is_move_start_threshold_position_2D_defined() const { return (drag.move_start_threshold_position_2D != Drag::Invalid_2D_Point); }
bool is_move_threshold_met(const Point& mouse_pos) const { bool is_move_threshold_met(const Point& mouse_pos) const {
return (std::abs(mouse_pos(0) - drag.move_start_threshold_position_2D(0)) > Drag::MoveThresholdPx) return (std::abs(mouse_pos(0) - drag.move_start_threshold_position_2D(0)) > Drag::MoveThresholdPx)
|| (std::abs(mouse_pos(1) - drag.move_start_threshold_position_2D(1)) > Drag::MoveThresholdPx); || (std::abs(mouse_pos(1) - drag.move_start_threshold_position_2D(1)) > Drag::MoveThresholdPx);
} }
#endif // ENABLE_MOVE_MIN_THRESHOLD
}; };
public: public:
class TransformationType
{
public:
enum Enum {
// Transforming in a world coordinate system
World = 0,
// Transforming in a local coordinate system
Local = 1,
// Absolute transformations, allowed in local coordinate system only.
Absolute = 0,
// Relative transformations, allowed in both local and world coordinate system.
Relative = 2,
// For group selection, the transformation is performed as if the group made a single solid body.
Joint = 0,
// For group selection, the transformation is performed on each object independently.
Independent = 4,
World_Relative_Joint = World | Relative | Joint,
World_Relative_Independent = World | Relative | Independent,
Local_Absolute_Joint = Local | Absolute | Joint,
Local_Absolute_Independent = Local | Absolute | Independent,
Local_Relative_Joint = Local | Relative | Joint,
Local_Relative_Independent = Local | Relative | Independent,
};
TransformationType() : m_value(World) {}
TransformationType(Enum value) : m_value(value) {}
TransformationType& operator=(Enum value) { m_value = value; return *this; }
Enum operator()() const { return m_value; }
bool has(Enum v) const { return ((unsigned int)m_value & (unsigned int)v) != 0; }
void set_world() { this->remove(Local); }
void set_local() { this->add(Local); }
void set_absolute() { this->remove(Relative); }
void set_relative() { this->add(Relative); }
void set_joint() { this->remove(Independent); }
void set_independent() { this->add(Independent); }
bool world() const { return ! this->has(Local); }
bool local() const { return this->has(Local); }
bool absolute() const { return ! this->has(Relative); }
bool relative() const { return this->has(Relative); }
bool joint() const { return ! this->has(Independent); }
bool independent() const { return this->has(Independent); }
private:
void add(Enum v) { m_value = Enum((unsigned int)m_value | (unsigned int)v); }
void remove(Enum v) { m_value = Enum((unsigned int)m_value & (~(unsigned int)v)); }
Enum m_value;
};
class Selection
{
public:
typedef std::set<unsigned int> IndicesList;
enum EMode : unsigned char
{
Volume,
Instance
};
enum EType : unsigned char
{
Invalid,
Empty,
WipeTower,
SingleModifier,
MultipleModifier,
SingleVolume,
MultipleVolume,
SingleFullObject,
MultipleFullObject,
SingleFullInstance,
MultipleFullInstance,
Mixed
};
private:
struct VolumeCache
{
private:
struct TransformCache
{
Vec3d position;
Vec3d rotation;
Vec3d scaling_factor;
Vec3d mirror;
Transform3d rotation_matrix;
Transform3d scale_matrix;
Transform3d mirror_matrix;
Transform3d full_matrix;
TransformCache();
explicit TransformCache(const Geometry::Transformation& transform);
};
TransformCache m_volume;
TransformCache m_instance;
public:
VolumeCache() {}
VolumeCache(const Geometry::Transformation& volume_transform, const Geometry::Transformation& instance_transform);
const Vec3d& get_volume_position() const { return m_volume.position; }
const Vec3d& get_volume_rotation() const { return m_volume.rotation; }
const Vec3d& get_volume_scaling_factor() const { return m_volume.scaling_factor; }
const Vec3d& get_volume_mirror() const { return m_volume.mirror; }
const Transform3d& get_volume_rotation_matrix() const { return m_volume.rotation_matrix; }
const Transform3d& get_volume_scale_matrix() const { return m_volume.scale_matrix; }
const Transform3d& get_volume_mirror_matrix() const { return m_volume.mirror_matrix; }
const Transform3d& get_volume_full_matrix() const { return m_volume.full_matrix; }
const Vec3d& get_instance_position() const { return m_instance.position; }
const Vec3d& get_instance_rotation() const { return m_instance.rotation; }
const Vec3d& get_instance_scaling_factor() const { return m_instance.scaling_factor; }
const Vec3d& get_instance_mirror() const { return m_instance.mirror; }
const Transform3d& get_instance_rotation_matrix() const { return m_instance.rotation_matrix; }
const Transform3d& get_instance_scale_matrix() const { return m_instance.scale_matrix; }
const Transform3d& get_instance_mirror_matrix() const { return m_instance.mirror_matrix; }
const Transform3d& get_instance_full_matrix() const { return m_instance.full_matrix; }
};
typedef std::map<unsigned int, VolumeCache> VolumesCache;
typedef std::set<int> InstanceIdxsList;
typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap;
struct Cache
{
// Cache of GLVolume derived transformation matrices, valid during mouse dragging.
VolumesCache volumes_data;
// Center of the dragged selection, valid during mouse dragging.
Vec3d dragging_center;
// Map from indices of ModelObject instances in Model::objects
// to a set of indices of ModelVolume instances in ModelObject::instances
// Here the index means a position inside the respective std::vector, not ModelID.
ObjectIdxsToInstanceIdxsMap content;
};
// Volumes owned by GLCanvas3D.
GLVolumePtrs* m_volumes;
// Model, not owned.
Model* m_model;
bool m_valid;
EMode m_mode;
EType m_type;
// set of indices to m_volumes
IndicesList m_list;
Cache m_cache;
mutable BoundingBoxf3 m_bounding_box;
mutable bool m_bounding_box_dirty;
#if ENABLE_RENDER_SELECTION_CENTER
GLUquadricObj* m_quadric;
#endif // ENABLE_RENDER_SELECTION_CENTER
mutable GLArrow m_arrow;
mutable GLCurvedArrow m_curved_arrow;
mutable float m_scale_factor;
public:
Selection();
#if ENABLE_RENDER_SELECTION_CENTER
~Selection();
#endif // ENABLE_RENDER_SELECTION_CENTER
void set_volumes(GLVolumePtrs* volumes);
bool init(bool useVBOs);
Model* get_model() const { return m_model; }
void set_model(Model* model);
EMode get_mode() const { return m_mode; }
void set_mode(EMode mode) { m_mode = mode; }
void add(unsigned int volume_idx, bool as_single_selection = true);
void remove(unsigned int volume_idx);
void add_object(unsigned int object_idx, bool as_single_selection = true);
void remove_object(unsigned int object_idx);
void add_instance(unsigned int object_idx, unsigned int instance_idx, bool as_single_selection = true);
void remove_instance(unsigned int object_idx, unsigned int instance_idx);
void add_volume(unsigned int object_idx, unsigned int volume_idx, int instance_idx, bool as_single_selection = true);
void remove_volume(unsigned int object_idx, unsigned int volume_idx);
void add_all();
// Update the selection based on the map from old indices to new indices after m_volumes changed.
// If the current selection is by instance, this call may select newly added volumes, if they belong to already selected instances.
void volumes_changed(const std::vector<size_t> &map_volume_old_to_new);
void clear();
bool is_empty() const { return m_type == Empty; }
bool is_wipe_tower() const { return m_type == WipeTower; }
bool is_modifier() const { return (m_type == SingleModifier) || (m_type == MultipleModifier); }
bool is_single_modifier() const { return m_type == SingleModifier; }
bool is_multiple_modifier() const { return m_type == MultipleModifier; }
bool is_single_full_instance() const;
bool is_multiple_full_instance() const { return m_type == MultipleFullInstance; }
bool is_single_full_object() const { return m_type == SingleFullObject; }
bool is_multiple_full_object() const { return m_type == MultipleFullObject; }
bool is_single_volume() const { return m_type == SingleVolume; }
bool is_multiple_volume() const { return m_type == MultipleVolume; }
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;
bool contains_volume(unsigned int volume_idx) const { return std::find(m_list.begin(), m_list.end(), volume_idx) != m_list.end(); }
bool requires_uniform_scale() const;
// Returns the the object id if the selection is from a single object, otherwise is -1
int get_object_idx() const;
// Returns the instance id if the selection is from a single object and from a single instance, otherwise is -1
int get_instance_idx() const;
// Returns the indices of selected instances.
// Can only be called if selection is from a single object.
const InstanceIdxsList& get_instance_idxs() const;
const IndicesList& get_volume_idxs() const { return m_list; }
const GLVolume* get_volume(unsigned int volume_idx) const;
const ObjectIdxsToInstanceIdxsMap& get_content() const { return m_cache.content; }
unsigned int volumes_count() const { return (unsigned int)m_list.size(); }
const BoundingBoxf3& get_bounding_box() const;
void start_dragging();
void translate(const Vec3d& displacement, bool local = false);
void rotate(const Vec3d& rotation, TransformationType transformation_type);
void flattening_rotate(const Vec3d& normal);
void scale(const Vec3d& scale, bool local);
void mirror(Axis axis);
void translate(unsigned int object_idx, const Vec3d& displacement);
void translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement);
void erase();
void render(float scale_factor = 1.0) const;
#if ENABLE_RENDER_SELECTION_CENTER
void render_center() const;
#endif // ENABLE_RENDER_SELECTION_CENTER
void render_sidebar_hints(const std::string& sidebar_field) const;
bool requires_local_axes() const;
private:
void _update_valid();
void _update_type();
void _set_caches();
void _add_volume(unsigned int volume_idx);
void _add_instance(unsigned int object_idx, unsigned int instance_idx);
void _add_object(unsigned int object_idx);
void _remove_volume(unsigned int volume_idx);
void _remove_instance(unsigned int object_idx, unsigned int instance_idx);
void _remove_object(unsigned int object_idx);
void _calc_bounding_box() const;
void _render_selected_volumes() const;
void _render_synchronized_volumes() const;
void _render_bounding_box(const BoundingBoxf3& box, float* color) const;
void _render_sidebar_position_hints(const std::string& sidebar_field) const;
void _render_sidebar_rotation_hints(const std::string& sidebar_field) const;
void _render_sidebar_scale_hints(const std::string& sidebar_field) const;
void _render_sidebar_size_hints(const std::string& sidebar_field) const;
void _render_sidebar_position_hint(Axis axis) const;
void _render_sidebar_rotation_hint(Axis axis) const;
void _render_sidebar_scale_hint(Axis axis) const;
void _render_sidebar_size_hint(Axis axis, double length) const;
enum SyncRotationType {
// Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
SYNC_ROTATION_NONE = 0,
// Synchronize fully. Used from "place on bed" feature.
SYNC_ROTATION_FULL = 1,
// Synchronize after rotation by an axis not parallel with Z.
SYNC_ROTATION_GENERAL = 2,
};
void _synchronize_unselected_instances(SyncRotationType sync_rotation_type);
void _synchronize_unselected_volumes();
void _ensure_on_bed();
};
class ClippingPlane class ClippingPlane
{ {
double m_data[4]; double m_data[4];
@ -741,7 +445,7 @@ private:
void set_flattening_data(const ModelObject* model_object); void set_flattening_data(const ModelObject* model_object);
void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection); void set_sla_support_data(ModelObject* model_object, const Selection& selection);
bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false); bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false);
void delete_current_grabber(bool delete_all = false); void delete_current_grabber(bool delete_all = false);
@ -872,7 +576,6 @@ private:
bool m_use_VBOs; bool m_use_VBOs;
bool m_apply_zoom_to_volumes_filter; bool m_apply_zoom_to_volumes_filter;
mutable int m_hover_volume_id; mutable int m_hover_volume_id;
bool m_toolbar_action_running;
bool m_warning_texture_enabled; bool m_warning_texture_enabled;
bool m_legend_texture_enabled; bool m_legend_texture_enabled;
bool m_picking_enabled; bool m_picking_enabled;
@ -951,9 +654,6 @@ public:
void enable_dynamic_background(bool enable); void enable_dynamic_background(bool enable);
void allow_multisample(bool allow); void allow_multisample(bool allow);
void enable_toolbar_item(const std::string& name, bool enable);
bool is_toolbar_item_pressed(const std::string& name) const;
void zoom_to_bed(); void zoom_to_bed();
void zoom_to_volumes(); void zoom_to_volumes();
void zoom_to_selection(); void zoom_to_selection();
@ -961,8 +661,6 @@ public:
void update_volumes_colors_by_extruder(); void update_volumes_colors_by_extruder();
void update_toolbar_items_visibility();
bool is_dragging() const { return m_gizmos.is_dragging() || m_moving; } bool is_dragging() const { return m_gizmos.is_dragging() || m_moving; }
void render(); void render();

View File

@ -30,6 +30,10 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent);
wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_3D, SimpleEvent); wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_3D, SimpleEvent);
wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent); wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
const GLToolbarItem::ActionCallback GLToolbarItem::Default_Action_Callback = [](){};
const GLToolbarItem::VisibilityCallback GLToolbarItem::Default_Visibility_Callback = []()->bool { return true; };
const GLToolbarItem::EnabledStateCallback GLToolbarItem::Default_Enabled_State_Callback = []()->bool { return true; };
GLToolbarItem::Data::Data() GLToolbarItem::Data::Data()
: name("") : name("")
#if ENABLE_SVG_ICONS #if ENABLE_SVG_ICONS
@ -39,19 +43,37 @@ GLToolbarItem::Data::Data()
, sprite_id(-1) , sprite_id(-1)
, is_toggable(false) , is_toggable(false)
, visible(true) , visible(true)
, action_callback(Default_Action_Callback)
, visibility_callback(Default_Visibility_Callback)
, enabled_state_callback(Default_Enabled_State_Callback)
{ {
} }
GLToolbarItem::GLToolbarItem(GLToolbarItem::EType type, const GLToolbarItem::Data& data) GLToolbarItem::GLToolbarItem(GLToolbarItem::EType type, const GLToolbarItem::Data& data)
: m_type(type) : m_type(type)
, m_state(Disabled) , m_state(Normal)
, m_data(data) , m_data(data)
{ {
} }
void GLToolbarItem::do_action(wxEvtHandler *target) bool GLToolbarItem::update_visibility()
{ {
wxPostEvent(target, SimpleEvent(m_data.action_event)); bool visible = m_data.visibility_callback();
bool ret = (m_data.visible != visible);
if (ret)
m_data.visible = visible;
return ret;
}
bool GLToolbarItem::update_enabled_state()
{
bool enabled = m_data.enabled_state_callback();
bool ret = (is_enabled() != enabled);
if (ret)
m_state = enabled ? GLToolbarItem::Normal : GLToolbarItem::Disabled;
return ret;
} }
void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const
@ -135,6 +157,8 @@ GLToolbar::GLToolbar(GLToolbar::EType type)
#if ENABLE_SVG_ICONS #if ENABLE_SVG_ICONS
, m_icons_texture_dirty(true) , m_icons_texture_dirty(true)
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
, m_mouse_capture({false, false, false})
, m_tooltip("")
{ {
} }
@ -299,30 +323,6 @@ float GLToolbar::get_height() const
return m_layout.height; return m_layout.height;
} }
void GLToolbar::enable_item(const std::string& name)
{
for (GLToolbarItem* item : m_items)
{
if ((item->get_name() == name) && (item->get_state() == GLToolbarItem::Disabled))
{
item->set_state(GLToolbarItem::Normal);
return;
}
}
}
void GLToolbar::disable_item(const std::string& name)
{
for (GLToolbarItem* item : m_items)
{
if (item->get_name() == name)
{
item->set_state(GLToolbarItem::Disabled);
return;
}
}
}
void GLToolbar::select_item(const std::string& name) void GLToolbar::select_item(const std::string& name)
{ {
if (is_item_disabled(name)) if (is_item_disabled(name))
@ -371,95 +371,12 @@ bool GLToolbar::is_item_visible(const std::string& name) const
return false; return false;
} }
void GLToolbar::set_item_visible(const std::string& name, bool visible) bool GLToolbar::update_items_state()
{ {
for (GLToolbarItem* item : m_items) bool ret = false;
{ ret |= update_items_visibility();
if ((item->get_name() == name) && (item->is_visible() != visible)) ret |= update_items_enabled_state();
{ return ret;
item->set_visible(visible);
m_layout.dirty = true;
break;
}
}
// updates separators visibility to avoid having two consecutive
bool any_item_visible = false;
for (GLToolbarItem* item : m_items)
{
if (!item->is_separator())
any_item_visible |= item->is_visible();
else
{
item->set_visible(any_item_visible);
any_item_visible = false;
}
}
}
std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
{
if (!m_enabled)
return "";
switch (m_layout.type)
{
default:
case Layout::Horizontal: { return update_hover_state_horizontal(mouse_pos, parent); }
case Layout::Vertical: { return update_hover_state_vertical(mouse_pos, parent); }
}
}
int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
{
if (!m_enabled)
return -1;
switch (m_layout.type)
{
default:
case Layout::Horizontal: { return contains_mouse_horizontal(mouse_pos, parent); }
case Layout::Vertical: { return contains_mouse_vertical(mouse_pos, parent); }
}
}
void GLToolbar::do_action(unsigned int item_id, GLCanvas3D& parent)
{
if (item_id < (unsigned int)m_items.size())
{
GLToolbarItem* item = m_items[item_id];
if ((item != nullptr) && !item->is_separator() && item->is_hovered())
{
if (item->is_toggable())
{
GLToolbarItem::EState state = item->get_state();
if (state == GLToolbarItem::Hover)
item->set_state(GLToolbarItem::HoverPressed);
else if (state == GLToolbarItem::HoverPressed)
item->set_state(GLToolbarItem::Hover);
parent.render();
item->do_action(parent.get_wxglcanvas());
}
else
{
if (m_type == Radio)
select_item(item->get_name());
else
item->set_state(GLToolbarItem::HoverPressed);
parent.render();
item->do_action(parent.get_wxglcanvas());
if ((m_type == Normal) && (item->get_state() != GLToolbarItem::Disabled))
{
// the item may get disabled during the action, if not, set it back to hover state
item->set_state(GLToolbarItem::Hover);
parent.render();
}
}
}
}
} }
void GLToolbar::render(const GLCanvas3D& parent) const void GLToolbar::render(const GLCanvas3D& parent) const
@ -487,6 +404,53 @@ void GLToolbar::render(const GLCanvas3D& parent) const
::glPopMatrix(); ::glPopMatrix();
} }
bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
{
Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY());
bool processed = false;
// mouse anywhere
if (evt.Moving())
m_tooltip = update_hover_state(mouse_pos, parent);
else if (evt.LeftUp())
m_mouse_capture.left = false;
else if (evt.MiddleUp())
m_mouse_capture.middle = false;
else if (evt.RightUp())
m_mouse_capture.right = false;
else if (m_mouse_capture.any() && evt.Dragging())
processed = true;
int item_id = contains_mouse(mouse_pos, parent);
if (item_id == -1)
{
// mouse is outside the toolbar
m_tooltip = "";
}
else
{
// mouse inside toolbar only
if (evt.LeftDown() || evt.LeftDClick())
{
m_mouse_capture.left = true;
if ((item_id != -2) && !m_items[item_id]->is_separator())
{
// mouse is inside an icon
do_action((unsigned int)item_id, parent);
processed = true;
}
}
else if (evt.MiddleDown())
m_mouse_capture.middle = true;
else if (evt.RightDown())
m_mouse_capture.right = true;
else if (evt.LeftUp())
processed = true;
}
return processed;
}
void GLToolbar::calc_layout() const void GLToolbar::calc_layout() const
{ {
switch (m_layout.type) switch (m_layout.type)
@ -576,6 +540,57 @@ float GLToolbar::get_main_size() const
return size; return size;
} }
void GLToolbar::do_action(unsigned int item_id, GLCanvas3D& parent)
{
if (item_id < (unsigned int)m_items.size())
{
GLToolbarItem* item = m_items[item_id];
if ((item != nullptr) && !item->is_separator() && item->is_hovered())
{
if (item->is_toggable())
{
GLToolbarItem::EState state = item->get_state();
if (state == GLToolbarItem::Hover)
item->set_state(GLToolbarItem::HoverPressed);
else if (state == GLToolbarItem::HoverPressed)
item->set_state(GLToolbarItem::Hover);
parent.render();
item->do_action();
}
else
{
if (m_type == Radio)
select_item(item->get_name());
else
item->set_state(GLToolbarItem::HoverPressed);
parent.render();
item->do_action();
if ((m_type == Normal) && (item->get_state() != GLToolbarItem::Disabled))
{
// the item may get disabled during the action, if not, set it back to hover state
item->set_state(GLToolbarItem::Hover);
parent.render();
}
}
}
}
}
std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
{
if (!m_enabled)
return "";
switch (m_layout.type)
{
default:
case Layout::Horizontal: { return update_hover_state_horizontal(mouse_pos, parent); }
case Layout::Vertical: { return update_hover_state_vertical(mouse_pos, parent); }
}
}
std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent) std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent)
{ {
// NB: mouse_pos is already scaled appropriately // NB: mouse_pos is already scaled appropriately
@ -785,6 +800,19 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
return tooltip; return tooltip;
} }
int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
{
if (!m_enabled)
return -1;
switch (m_layout.type)
{
default:
case Layout::Horizontal: { return contains_mouse_horizontal(mouse_pos, parent); }
case Layout::Vertical: { return contains_mouse_vertical(mouse_pos, parent); }
}
}
int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
{ {
// NB: mouse_pos is already scaled appropriately // NB: mouse_pos is already scaled appropriately
@ -808,8 +836,6 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
float scaled_separator_size = m_layout.separator_size * factor; float scaled_separator_size = m_layout.separator_size * factor;
float scaled_gap_size = m_layout.gap_size * factor; float scaled_gap_size = m_layout.gap_size * factor;
float scaled_border = m_layout.border * factor; float scaled_border = m_layout.border * factor;
float separator_stride = scaled_separator_size + scaled_gap_size;
float icon_stride = scaled_icons_size + scaled_gap_size;
float left = m_layout.left + scaled_border; float left = m_layout.left + scaled_border;
float top = m_layout.top - scaled_border; float top = m_layout.top - scaled_border;
@ -824,16 +850,46 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
continue; continue;
if (item->is_separator()) if (item->is_separator())
left += separator_stride; {
float right = left + scaled_separator_size;
float bottom = top - scaled_icons_size;
// mouse inside the separator
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
return id;
left = right;
right += scaled_gap_size;
if (id < m_items.size() - 1)
{
// mouse inside the gap
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
return -2;
}
left = right;
}
else else
{ {
float right = left + scaled_icons_size; float right = left + scaled_icons_size;
float bottom = top - scaled_icons_size; float bottom = top - scaled_icons_size;
// mouse inside the icon
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
return id; return id;
left += icon_stride; left = right;
right += scaled_gap_size;
if (id < m_items.size() - 1)
{
// mouse inside the gap
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
return -2;
}
left = right;
} }
} }
@ -864,9 +920,6 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
float scaled_gap_size = m_layout.gap_size * factor; float scaled_gap_size = m_layout.gap_size * factor;
float scaled_border = m_layout.border * factor; float scaled_border = m_layout.border * factor;
float separator_stride = scaled_separator_size + scaled_gap_size;
float icon_stride = scaled_icons_size + scaled_gap_size;
float left = m_layout.left + scaled_border; float left = m_layout.left + scaled_border;
float top = m_layout.top - scaled_border; float top = m_layout.top - scaled_border;
@ -880,16 +933,46 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
continue; continue;
if (item->is_separator()) if (item->is_separator())
top -= separator_stride; {
float right = left + scaled_icons_size;
float bottom = top - scaled_separator_size;
// mouse inside the separator
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
return id;
top = bottom;
bottom -= scaled_gap_size;
if (id < m_items.size() - 1)
{
// mouse inside the gap
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
return -2;
}
top = bottom;
}
else else
{ {
float right = left + scaled_icons_size; float right = left + scaled_icons_size;
float bottom = top - scaled_icons_size; float bottom = top - scaled_icons_size;
// mouse inside the icon
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
return id; return id;
top -= icon_stride; top = bottom;
bottom -= scaled_gap_size;
if (id < m_items.size() - 1)
{
// mouse inside the gap
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
return -2;
}
top = bottom;
} }
} }
@ -1244,5 +1327,48 @@ bool GLToolbar::generate_icons_texture() const
} }
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
bool GLToolbar::update_items_visibility()
{
bool ret = false;
for (GLToolbarItem* item : m_items)
{
ret |= item->update_visibility();
}
if (ret)
m_layout.dirty = true;
// updates separators visibility to avoid having two of them consecutive
bool any_item_visible = false;
for (GLToolbarItem* item : m_items)
{
if (!item->is_separator())
any_item_visible |= item->is_visible();
else
{
item->set_visible(any_item_visible);
any_item_visible = false;
}
}
return ret;
}
bool GLToolbar::update_items_enabled_state()
{
bool ret = false;
for (GLToolbarItem* item : m_items)
{
ret |= item->update_enabled_state();
}
if (ret)
m_layout.dirty = true;
return ret;
}
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View File

@ -31,6 +31,10 @@ wxDECLARE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
class GLToolbarItem class GLToolbarItem
{ {
public: public:
typedef std::function<void()> ActionCallback;
typedef std::function<bool()> VisibilityCallback;
typedef std::function<bool()> EnabledStateCallback;
enum EType : unsigned char enum EType : unsigned char
{ {
Action, Action,
@ -57,12 +61,18 @@ public:
std::string tooltip; std::string tooltip;
unsigned int sprite_id; unsigned int sprite_id;
bool is_toggable; bool is_toggable;
wxEventType action_event;
bool visible; bool visible;
ActionCallback action_callback;
VisibilityCallback visibility_callback;
EnabledStateCallback enabled_state_callback;
Data(); Data();
}; };
static const ActionCallback Default_Action_Callback;
static const VisibilityCallback Default_Visibility_Callback;
static const EnabledStateCallback Default_Enabled_State_Callback;
private: private:
EType m_type; EType m_type;
EState m_state; EState m_state;
@ -80,7 +90,7 @@ public:
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
const std::string& get_tooltip() const { return m_data.tooltip; } const std::string& get_tooltip() const { return m_data.tooltip; }
void do_action(wxEvtHandler *target); void do_action() { m_data.action_callback(); }
bool is_enabled() const { return m_state != Disabled; } bool is_enabled() const { return m_state != Disabled; }
bool is_disabled() const { return m_state == Disabled; } bool is_disabled() const { return m_state == Disabled; }
@ -89,13 +99,20 @@ public:
bool is_toggable() const { return m_data.is_toggable; } bool is_toggable() const { return m_data.is_toggable; }
bool is_visible() const { return m_data.visible; } bool is_visible() const { return m_data.visible; }
void set_visible(bool visible) { m_data.visible = visible; }
bool is_separator() const { return m_type == Separator; } bool is_separator() const { return m_type == Separator; }
// returns true if the state changes
bool update_visibility();
// returns true if the state changes
bool update_enabled_state();
void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const; void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
private: private:
GLTexture::Quad_UVs get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const; GLTexture::Quad_UVs get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
void set_visible(bool visible) { m_data.visible = visible; }
friend class GLToolbar;
}; };
#if !ENABLE_SVG_ICONS #if !ENABLE_SVG_ICONS
@ -214,6 +231,18 @@ private:
ItemsList m_items; ItemsList m_items;
struct MouseCapture
{
bool left;
bool middle;
bool right;
bool any() const { return left || middle || right; }
};
MouseCapture m_mouse_capture;
std::string m_tooltip;
public: public:
#if ENABLE_SVG_ICONS #if ENABLE_SVG_ICONS
GLToolbar(EType type, const std::string& name); GLToolbar(EType type, const std::string& name);
@ -253,24 +282,22 @@ public:
float get_width() const; float get_width() const;
float get_height() const; float get_height() const;
void enable_item(const std::string& name);
void disable_item(const std::string& name);
void select_item(const std::string& name); void select_item(const std::string& name);
bool is_item_pressed(const std::string& name) const; bool is_item_pressed(const std::string& name) const;
bool is_item_disabled(const std::string& name) const; bool is_item_disabled(const std::string& name) const;
bool is_item_visible(const std::string& name) const; bool is_item_visible(const std::string& name) const;
void set_item_visible(const std::string& name, bool visible);
std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent); const std::string& get_tooltip() const { return m_tooltip; }
// returns the id of the item under the given mouse position or -1 if none
int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
void do_action(unsigned int item_id, GLCanvas3D& parent); // returns true if any item changed its state
bool update_items_state();
void render(const GLCanvas3D& parent) const; void render(const GLCanvas3D& parent) const;
bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent);
private: private:
void calc_layout() const; void calc_layout() const;
float get_width_horizontal() const; float get_width_horizontal() const;
@ -278,8 +305,12 @@ private:
float get_height_horizontal() const; float get_height_horizontal() const;
float get_height_vertical() const; float get_height_vertical() const;
float get_main_size() const; float get_main_size() const;
void do_action(unsigned int item_id, GLCanvas3D& parent);
std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent);
std::string update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent); std::string update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent);
std::string update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent); std::string update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent);
// returns the id of the item under the given mouse position or -1 if none
int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const; int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const; int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
@ -289,6 +320,11 @@ private:
#if ENABLE_SVG_ICONS #if ENABLE_SVG_ICONS
bool generate_icons_texture() const; bool generate_icons_texture() const;
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
// returns true if any item changed its state
bool update_items_visibility();
// returns true if any item changed its state
bool update_items_enabled_state();
}; };
} // namespace GUI } // namespace GUI

View File

@ -10,6 +10,7 @@
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "LambdaObjectDialog.hpp" #include "LambdaObjectDialog.hpp"
#include "GLCanvas3D.hpp" #include "GLCanvas3D.hpp"
#include "Selection.hpp"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include "slic3r/Utils/FixModelByWin10.hpp" #include "slic3r/Utils/FixModelByWin10.hpp"
@ -1274,7 +1275,7 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
if (obj_idx < 0) if (obj_idx < 0)
return; return;
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
assert(obj_idx == selection.get_object_idx()); assert(obj_idx == selection.get_object_idx());
/** Any changes of the Object's composition is duplicated for all Object's Instances /** Any changes of the Object's composition is duplicated for all Object's Instances
@ -1562,7 +1563,7 @@ bool ObjectList::selected_instances_of_same_object()
bool ObjectList::can_split_instances() bool ObjectList::can_split_instances()
{ {
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
return selection.is_multiple_full_instance() || selection.is_single_full_instance(); return selection.is_multiple_full_instance() || selection.is_single_full_instance();
} }
@ -1872,7 +1873,7 @@ bool ObjectList::multiple_selection() const
void ObjectList::update_selections() void ObjectList::update_selections()
{ {
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
wxDataViewItemArray sels; wxDataViewItemArray sels;
// We doesn't update selection if SettingsItem for the current object/part is selected // We doesn't update selection if SettingsItem for the current object/part is selected
@ -1970,7 +1971,7 @@ void ObjectList::update_selections()
void ObjectList::update_selections_on_canvas() void ObjectList::update_selections_on_canvas()
{ {
GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
const int sel_cnt = GetSelectedItemsCount(); const int sel_cnt = GetSelectedItemsCount();
if (sel_cnt == 0) { if (sel_cnt == 0) {
@ -1979,7 +1980,7 @@ void ObjectList::update_selections_on_canvas()
return; return;
} }
auto add_to_selection = [this](const wxDataViewItem& item, GLCanvas3D::Selection& selection, bool as_single_selection) auto add_to_selection = [this](const wxDataViewItem& item, Selection& selection, bool as_single_selection)
{ {
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
selection.add_object(m_objects_model->GetIdByItem(item), as_single_selection); selection.add_object(m_objects_model->GetIdByItem(item), as_single_selection);
@ -2239,7 +2240,7 @@ void ObjectList::instances_to_separated_object(const int obj_idx, const std::set
void ObjectList::split_instances() void ObjectList::split_instances()
{ {
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
const int obj_idx = selection.get_object_idx(); const int obj_idx = selection.get_object_idx();
if (obj_idx == -1) if (obj_idx == -1)
return; return;

View File

@ -7,6 +7,7 @@
#include "PresetBundle.hpp" #include "PresetBundle.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "libslic3r/Geometry.hpp" #include "libslic3r/Geometry.hpp"
#include "Selection.hpp"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@ -155,7 +156,7 @@ void ObjectManipulation::UpdateAndShow(const bool show)
OG_Settings::UpdateAndShow(show); OG_Settings::UpdateAndShow(show);
} }
void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection) void ObjectManipulation::update_settings_value(const Selection& selection)
{ {
m_new_move_label_string = L("Position"); m_new_move_label_string = L("Position");
m_new_rotate_label_string = L("Rotation"); m_new_rotate_label_string = L("Rotation");
@ -348,7 +349,7 @@ void ObjectManipulation::reset_settings_value()
void ObjectManipulation::change_position_value(const Vec3d& position) void ObjectManipulation::change_position_value(const Vec3d& position)
{ {
auto canvas = wxGetApp().plater()->canvas3D(); auto canvas = wxGetApp().plater()->canvas3D();
GLCanvas3D::Selection& selection = canvas->get_selection(); Selection& selection = canvas->get_selection();
selection.start_dragging(); selection.start_dragging();
selection.translate(position - m_cache.position, selection.requires_local_axes()); selection.translate(position - m_cache.position, selection.requires_local_axes());
canvas->do_move(); canvas->do_move();
@ -359,13 +360,13 @@ void ObjectManipulation::change_position_value(const Vec3d& position)
void ObjectManipulation::change_rotation_value(const Vec3d& rotation) void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
{ {
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
const GLCanvas3D::Selection& selection = canvas->get_selection(); const Selection& selection = canvas->get_selection();
GLCanvas3D::TransformationType transformation_type(GLCanvas3D::TransformationType::World_Relative_Joint); TransformationType transformation_type(TransformationType::World_Relative_Joint);
if (selection.is_single_full_instance() || selection.requires_local_axes()) if (selection.is_single_full_instance() || selection.requires_local_axes())
transformation_type.set_independent(); transformation_type.set_independent();
if (selection.is_single_full_instance()) { if (selection.is_single_full_instance()) {
//FIXME GLCanvas3D::Selection::rotate() does not process absoulte rotations correctly: It does not recognize the axis index, which was changed. //FIXME Selection::rotate() does not process absoulte rotations correctly: It does not recognize the axis index, which was changed.
// transformation_type.set_absolute(); // transformation_type.set_absolute();
transformation_type.set_local(); transformation_type.set_local();
} }
@ -384,7 +385,7 @@ void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
void ObjectManipulation::change_scale_value(const Vec3d& scale) void ObjectManipulation::change_scale_value(const Vec3d& scale)
{ {
Vec3d scaling_factor = scale; Vec3d scaling_factor = scale;
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
if (m_uniform_scale || selection.requires_uniform_scale()) if (m_uniform_scale || selection.requires_uniform_scale())
{ {
Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs(); Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs();
@ -418,7 +419,7 @@ void ObjectManipulation::change_scale_value(const Vec3d& scale)
void ObjectManipulation::change_size_value(const Vec3d& size) void ObjectManipulation::change_size_value(const Vec3d& size)
{ {
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
Vec3d ref_size = m_cache.size; Vec3d ref_size = m_cache.size;
if (selection.is_single_volume() || selection.is_single_modifier()) if (selection.is_single_volume() || selection.is_single_modifier())

View File

@ -12,6 +12,7 @@ class PrusaLockButton;
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
class Selection;
class ObjectManipulation : public OG_Settings class ObjectManipulation : public OG_Settings
{ {
@ -90,7 +91,7 @@ public:
bool IsShown() override; bool IsShown() override;
void UpdateAndShow(const bool show) override; void UpdateAndShow(const bool show) override;
void update_settings_value(const GLCanvas3D::Selection& selection); void update_settings_value(const Selection& selection);
// Called from the App to update the UI if dirty. // Called from the App to update the UI if dirty.
void update_if_dirty(); void update_if_dirty();

View File

@ -110,18 +110,6 @@ void View3D::mirror_selection(Axis axis)
m_canvas->mirror_selection(axis); m_canvas->mirror_selection(axis);
} }
void View3D::update_toolbar_items_visibility()
{
if (m_canvas != nullptr)
m_canvas->update_toolbar_items_visibility();
}
void View3D::enable_toolbar_item(const std::string& name, bool enable)
{
if (m_canvas != nullptr)
m_canvas->enable_toolbar_item(name, enable);
}
int View3D::check_volumes_outside_state() const int View3D::check_volumes_outside_state() const
{ {
return (m_canvas != nullptr) ? m_canvas->check_volumes_outside_state() : false; return (m_canvas != nullptr) ? m_canvas->check_volumes_outside_state() : false;

View File

@ -50,8 +50,6 @@ public:
void delete_selected(); void delete_selected();
void mirror_selection(Axis axis); void mirror_selection(Axis axis);
void update_toolbar_items_visibility();
void enable_toolbar_item(const std::string& name, bool enable);
int check_volumes_outside_state() const; int check_volumes_outside_state() const;
bool is_layers_editing_enabled() const; bool is_layers_editing_enabled() const;

View File

@ -184,7 +184,7 @@ void GLGizmoBase::disable_grabber(unsigned int id)
on_disable_grabber(id); on_disable_grabber(id);
} }
void GLGizmoBase::start_dragging(const GLCanvas3D::Selection& selection) void GLGizmoBase::start_dragging(const Selection& selection)
{ {
m_dragging = true; m_dragging = true;
@ -208,7 +208,7 @@ void GLGizmoBase::stop_dragging()
on_stop_dragging(); on_stop_dragging();
} }
void GLGizmoBase::update(const UpdateData& data, const GLCanvas3D::Selection& selection) void GLGizmoBase::update(const UpdateData& data, const Selection& selection)
{ {
if (m_hover_id != -1) if (m_hover_id != -1)
on_update(data, selection); on_update(data, selection);

View File

@ -5,6 +5,7 @@
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/I18N.hpp" #include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/Selection.hpp"
class wxWindow; class wxWindow;
@ -126,7 +127,7 @@ public:
const std::string& get_icon_filename() const { return m_icon_filename; } const std::string& get_icon_filename() const { return m_icon_filename; }
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
bool is_activable(const GLCanvas3D::Selection& selection) const { return on_is_activable(selection); } bool is_activable(const Selection& selection) const { return on_is_activable(selection); }
bool is_selectable() const { return on_is_selectable(); } bool is_selectable() const { return on_is_selectable(); }
unsigned int get_sprite_id() const { return m_sprite_id; } unsigned int get_sprite_id() const { return m_sprite_id; }
@ -139,31 +140,31 @@ public:
void enable_grabber(unsigned int id); void enable_grabber(unsigned int id);
void disable_grabber(unsigned int id); void disable_grabber(unsigned int id);
void start_dragging(const GLCanvas3D::Selection& selection); void start_dragging(const Selection& selection);
void stop_dragging(); void stop_dragging();
bool is_dragging() const { return m_dragging; } bool is_dragging() const { return m_dragging; }
void update(const UpdateData& data, const GLCanvas3D::Selection& selection); void update(const UpdateData& data, const Selection& selection);
void render(const GLCanvas3D::Selection& selection) const { on_render(selection); } void render(const Selection& selection) const { on_render(selection); }
void render_for_picking(const GLCanvas3D::Selection& selection) const { on_render_for_picking(selection); } void render_for_picking(const Selection& selection) const { on_render_for_picking(selection); }
void render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { on_render_input_window(x, y, bottom_limit, selection); } void render_input_window(float x, float y, float bottom_limit, const Selection& selection) { on_render_input_window(x, y, bottom_limit, selection); }
protected: protected:
virtual bool on_init() = 0; virtual bool on_init() = 0;
virtual std::string on_get_name() const = 0; virtual std::string on_get_name() const = 0;
virtual void on_set_state() {} virtual void on_set_state() {}
virtual void on_set_hover_id() {} virtual void on_set_hover_id() {}
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return true; } virtual bool on_is_activable(const Selection& selection) const { return true; }
virtual bool on_is_selectable() const { return true; } virtual bool on_is_selectable() const { return true; }
virtual void on_enable_grabber(unsigned int id) {} virtual void on_enable_grabber(unsigned int id) {}
virtual void on_disable_grabber(unsigned int id) {} virtual void on_disable_grabber(unsigned int id) {}
virtual void on_start_dragging(const GLCanvas3D::Selection& selection) {} virtual void on_start_dragging(const Selection& selection) {}
virtual void on_stop_dragging() {} virtual void on_stop_dragging() {}
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) = 0; virtual void on_update(const UpdateData& data, const Selection& selection) = 0;
virtual void on_render(const GLCanvas3D::Selection& selection) const = 0; virtual void on_render(const Selection& selection) const = 0;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const = 0; virtual void on_render_for_picking(const Selection& selection) const = 0;
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) {} virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection) {}
// Returns the picking color for the given id, based on the BASE_ID constant // Returns the picking color for the given id, based on the BASE_ID constant
// No check is made for clashing with other picking color (i.e. GLVolumes) // No check is made for clashing with other picking color (i.e. GLVolumes)

View File

@ -101,12 +101,12 @@ void GLGizmoCut::on_set_state()
} }
} }
bool GLGizmoCut::on_is_activable(const GLCanvas3D::Selection& selection) const bool GLGizmoCut::on_is_activable(const Selection& selection) const
{ {
return selection.is_single_full_instance() && !selection.is_wipe_tower(); return selection.is_single_full_instance() && !selection.is_wipe_tower();
} }
void GLGizmoCut::on_start_dragging(const GLCanvas3D::Selection& selection) void GLGizmoCut::on_start_dragging(const Selection& selection)
{ {
if (m_hover_id == -1) { return; } if (m_hover_id == -1) { return; }
@ -118,14 +118,14 @@ void GLGizmoCut::on_start_dragging(const GLCanvas3D::Selection& selection)
m_drag_center(2) = m_cut_z; m_drag_center(2) = m_cut_z;
} }
void GLGizmoCut::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) void GLGizmoCut::on_update(const UpdateData& data, const Selection& selection)
{ {
if (m_hover_id != -1) { if (m_hover_id != -1) {
set_cut_z(m_start_z + calc_projection(data.mouse_ray)); set_cut_z(m_start_z + calc_projection(data.mouse_ray));
} }
} }
void GLGizmoCut::on_render(const GLCanvas3D::Selection& selection) const void GLGizmoCut::on_render(const Selection& selection) const
{ {
if (m_grabbers[0].dragging) { if (m_grabbers[0].dragging) {
set_tooltip("Z: " + format(m_cut_z, 2)); set_tooltip("Z: " + format(m_cut_z, 2));
@ -176,14 +176,14 @@ void GLGizmoCut::on_render(const GLCanvas3D::Selection& selection) const
m_grabbers[0].render(m_hover_id == 0, box.max_size()); m_grabbers[0].render(m_hover_id == 0, box.max_size());
} }
void GLGizmoCut::on_render_for_picking(const GLCanvas3D::Selection& selection) const void GLGizmoCut::on_render_for_picking(const Selection& selection) const
{ {
::glDisable(GL_DEPTH_TEST); ::glDisable(GL_DEPTH_TEST);
render_grabbers_for_picking(selection.get_bounding_box()); render_grabbers_for_picking(selection.get_bounding_box());
} }
void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
{ {
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
m_imgui->set_next_window_bg_alpha(0.5f); m_imgui->set_next_window_bg_alpha(0.5f);
@ -207,7 +207,7 @@ void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, co
} }
} }
void GLGizmoCut::update_max_z(const GLCanvas3D::Selection& selection) const void GLGizmoCut::update_max_z(const Selection& selection) const
{ {
m_max_z = selection.get_bounding_box().size()(2); m_max_z = selection.get_bounding_box().size()(2);
set_cut_z(m_cut_z); set_cut_z(m_cut_z);
@ -219,7 +219,7 @@ void GLGizmoCut::set_cut_z(double cut_z) const
m_cut_z = std::max(0.0, std::min(m_max_z, cut_z)); m_cut_z = std::max(0.0, std::min(m_max_z, cut_z));
} }
void GLGizmoCut::perform_cut(const GLCanvas3D::Selection& selection) void GLGizmoCut::perform_cut(const Selection& selection)
{ {
const auto instance_idx = selection.get_instance_idx(); const auto instance_idx = selection.get_instance_idx();
const auto object_idx = selection.get_object_idx(); const auto object_idx = selection.get_object_idx();

View File

@ -33,17 +33,17 @@ protected:
virtual bool on_init(); virtual bool on_init();
virtual std::string on_get_name() const; virtual std::string on_get_name() const;
virtual void on_set_state(); virtual void on_set_state();
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const; virtual bool on_is_activable(const Selection& selection) const;
virtual void on_start_dragging(const GLCanvas3D::Selection& selection); virtual void on_start_dragging(const Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); virtual void on_update(const UpdateData& data, const Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const; virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; virtual void on_render_for_picking(const Selection& selection) const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection);
private: private:
void update_max_z(const GLCanvas3D::Selection& selection) const; void update_max_z(const Selection& selection) const;
void set_cut_z(double cut_z) const; void set_cut_z(double cut_z) const;
void perform_cut(const GLCanvas3D::Selection& selection); void perform_cut(const Selection& selection);
double calc_projection(const Linef3& mouse_ray) const; double calc_projection(const Linef3& mouse_ray) const;
}; };

View File

@ -32,12 +32,12 @@ std::string GLGizmoFlatten::on_get_name() const
return L("Place on face [F]"); return L("Place on face [F]");
} }
bool GLGizmoFlatten::on_is_activable(const GLCanvas3D::Selection& selection) const bool GLGizmoFlatten::on_is_activable(const Selection& selection) const
{ {
return selection.is_single_full_instance(); return selection.is_single_full_instance();
} }
void GLGizmoFlatten::on_start_dragging(const GLCanvas3D::Selection& selection) void GLGizmoFlatten::on_start_dragging(const Selection& selection)
{ {
if (m_hover_id != -1) if (m_hover_id != -1)
{ {
@ -47,7 +47,7 @@ void GLGizmoFlatten::on_start_dragging(const GLCanvas3D::Selection& selection)
} }
} }
void GLGizmoFlatten::on_render(const GLCanvas3D::Selection& selection) const void GLGizmoFlatten::on_render(const Selection& selection) const
{ {
::glClear(GL_DEPTH_BUFFER_BIT); ::glClear(GL_DEPTH_BUFFER_BIT);
@ -83,7 +83,7 @@ void GLGizmoFlatten::on_render(const GLCanvas3D::Selection& selection) const
::glDisable(GL_BLEND); ::glDisable(GL_BLEND);
} }
void GLGizmoFlatten::on_render_for_picking(const GLCanvas3D::Selection& selection) const void GLGizmoFlatten::on_render_for_picking(const Selection& selection) const
{ {
::glDisable(GL_DEPTH_TEST); ::glDisable(GL_DEPTH_TEST);
::glDisable(GL_BLEND); ::glDisable(GL_BLEND);

View File

@ -49,11 +49,11 @@ public:
protected: protected:
virtual bool on_init(); virtual bool on_init();
virtual std::string on_get_name() const; virtual std::string on_get_name() const;
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const; virtual bool on_is_activable(const Selection& selection) const;
virtual void on_start_dragging(const GLCanvas3D::Selection& selection); virtual void on_start_dragging(const Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) {} virtual void on_update(const UpdateData& data, const Selection& selection) {}
virtual void on_render(const GLCanvas3D::Selection& selection) const; virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; virtual void on_render_for_picking(const Selection& selection) const;
virtual void on_set_state() virtual void on_set_state()
{ {
if (m_state == On && is_plane_update_necessary()) if (m_state == On && is_plane_update_necessary())

View File

@ -51,7 +51,7 @@ std::string GLGizmoMove3D::on_get_name() const
return L("Move [M]"); return L("Move [M]");
} }
void GLGizmoMove3D::on_start_dragging(const GLCanvas3D::Selection& selection) void GLGizmoMove3D::on_start_dragging(const Selection& selection)
{ {
if (m_hover_id != -1) if (m_hover_id != -1)
{ {
@ -69,7 +69,7 @@ void GLGizmoMove3D::on_stop_dragging()
m_displacement = Vec3d::Zero(); m_displacement = Vec3d::Zero();
} }
void GLGizmoMove3D::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) void GLGizmoMove3D::on_update(const UpdateData& data, const Selection& selection)
{ {
if (m_hover_id == 0) if (m_hover_id == 0)
m_displacement(0) = calc_projection(data); m_displacement(0) = calc_projection(data);
@ -79,7 +79,7 @@ void GLGizmoMove3D::on_update(const UpdateData& data, const GLCanvas3D::Selectio
m_displacement(2) = calc_projection(data); m_displacement(2) = calc_projection(data);
} }
void GLGizmoMove3D::on_render(const GLCanvas3D::Selection& selection) const void GLGizmoMove3D::on_render(const Selection& selection) const
{ {
bool show_position = selection.is_single_full_instance(); bool show_position = selection.is_single_full_instance();
const Vec3d& position = selection.get_bounding_box().center(); const Vec3d& position = selection.get_bounding_box().center();
@ -155,7 +155,7 @@ void GLGizmoMove3D::on_render(const GLCanvas3D::Selection& selection) const
} }
} }
void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const void GLGizmoMove3D::on_render_for_picking(const Selection& selection) const
{ {
::glDisable(GL_DEPTH_TEST); ::glDisable(GL_DEPTH_TEST);
@ -166,7 +166,7 @@ void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection
render_grabber_extension(Z, box, true); render_grabber_extension(Z, box, true);
} }
void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
{ {
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
bool show_position = selection.is_single_full_instance(); bool show_position = selection.is_single_full_instance();

View File

@ -37,12 +37,12 @@ public:
protected: protected:
virtual bool on_init(); virtual bool on_init();
virtual std::string on_get_name() const; virtual std::string on_get_name() const;
virtual void on_start_dragging(const GLCanvas3D::Selection& selection); virtual void on_start_dragging(const Selection& selection);
virtual void on_stop_dragging(); virtual void on_stop_dragging();
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); virtual void on_update(const UpdateData& data, const Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const; virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; virtual void on_render_for_picking(const Selection& selection) const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection);
private: private:
double calc_projection(const UpdateData& data) const; double calc_projection(const UpdateData& data) const;

View File

@ -80,7 +80,7 @@ bool GLGizmoRotate::on_init()
return true; return true;
} }
void GLGizmoRotate::on_start_dragging(const GLCanvas3D::Selection& selection) void GLGizmoRotate::on_start_dragging(const Selection& selection)
{ {
const BoundingBoxf3& box = selection.get_bounding_box(); const BoundingBoxf3& box = selection.get_bounding_box();
m_center = box.center(); m_center = box.center();
@ -91,7 +91,7 @@ void GLGizmoRotate::on_start_dragging(const GLCanvas3D::Selection& selection)
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth; m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
} }
void GLGizmoRotate::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) void GLGizmoRotate::on_update(const UpdateData& data, const Selection& selection)
{ {
Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, selection)); Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, selection));
@ -126,7 +126,7 @@ void GLGizmoRotate::on_update(const UpdateData& data, const GLCanvas3D::Selectio
m_angle = theta; m_angle = theta;
} }
void GLGizmoRotate::on_render(const GLCanvas3D::Selection& selection) const void GLGizmoRotate::on_render(const Selection& selection) const
{ {
if (!m_grabbers[0].enabled) if (!m_grabbers[0].enabled)
return; return;
@ -183,7 +183,7 @@ void GLGizmoRotate::on_render(const GLCanvas3D::Selection& selection) const
::glPopMatrix(); ::glPopMatrix();
} }
void GLGizmoRotate::on_render_for_picking(const GLCanvas3D::Selection& selection) const void GLGizmoRotate::on_render_for_picking(const Selection& selection) const
{ {
::glDisable(GL_DEPTH_TEST); ::glDisable(GL_DEPTH_TEST);
@ -347,7 +347,7 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
::glDisable(GL_LIGHTING); ::glDisable(GL_LIGHTING);
} }
void GLGizmoRotate::transform_to_local(const GLCanvas3D::Selection& selection) const void GLGizmoRotate::transform_to_local(const Selection& selection) const
{ {
::glTranslated(m_center(0), m_center(1), m_center(2)); ::glTranslated(m_center(0), m_center(1), m_center(2));
@ -380,7 +380,7 @@ void GLGizmoRotate::transform_to_local(const GLCanvas3D::Selection& selection) c
} }
} }
Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const GLCanvas3D::Selection& selection) const Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const
{ {
double half_pi = 0.5 * (double)PI; double half_pi = 0.5 * (double)PI;
@ -457,7 +457,7 @@ std::string GLGizmoRotate3D::on_get_name() const
return L("Rotate [R]"); return L("Rotate [R]");
} }
void GLGizmoRotate3D::on_start_dragging(const GLCanvas3D::Selection& selection) void GLGizmoRotate3D::on_start_dragging(const Selection& selection)
{ {
if ((0 <= m_hover_id) && (m_hover_id < 3)) if ((0 <= m_hover_id) && (m_hover_id < 3))
m_gizmos[m_hover_id].start_dragging(selection); m_gizmos[m_hover_id].start_dragging(selection);
@ -469,7 +469,7 @@ void GLGizmoRotate3D::on_stop_dragging()
m_gizmos[m_hover_id].stop_dragging(); m_gizmos[m_hover_id].stop_dragging();
} }
void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const void GLGizmoRotate3D::on_render(const Selection& selection) const
{ {
::glClear(GL_DEPTH_BUFFER_BIT); ::glClear(GL_DEPTH_BUFFER_BIT);
@ -483,7 +483,7 @@ void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const
m_gizmos[Z].render(selection); m_gizmos[Z].render(selection);
} }
void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
{ {
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
Vec3d rotation(Geometry::rad2deg(m_gizmos[0].get_angle()), Geometry::rad2deg(m_gizmos[1].get_angle()), Geometry::rad2deg(m_gizmos[2].get_angle())); Vec3d rotation(Geometry::rad2deg(m_gizmos[0].get_angle()), Geometry::rad2deg(m_gizmos[1].get_angle()), Geometry::rad2deg(m_gizmos[2].get_angle()));

View File

@ -52,10 +52,10 @@ public:
protected: protected:
virtual bool on_init(); virtual bool on_init();
virtual std::string on_get_name() const { return ""; } virtual std::string on_get_name() const { return ""; }
virtual void on_start_dragging(const GLCanvas3D::Selection& selection); virtual void on_start_dragging(const Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); virtual void on_update(const UpdateData& data, const Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const; virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; virtual void on_render_for_picking(const Selection& selection) const;
private: private:
void render_circle() const; void render_circle() const;
@ -66,9 +66,9 @@ private:
void render_grabber(const BoundingBoxf3& box) const; void render_grabber(const BoundingBoxf3& box) const;
void render_grabber_extension(const BoundingBoxf3& box, bool picking) const; void render_grabber_extension(const BoundingBoxf3& box, bool picking) const;
void transform_to_local(const GLCanvas3D::Selection& selection) const; void transform_to_local(const Selection& selection) const;
// returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate // returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate
Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const GLCanvas3D::Selection& selection) const; Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const;
}; };
class GLGizmoRotate3D : public GLGizmoBase class GLGizmoRotate3D : public GLGizmoBase
@ -102,7 +102,7 @@ protected:
m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1); m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
} }
} }
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); } virtual bool on_is_activable(const Selection& selection) const { return !selection.is_wipe_tower(); }
virtual void on_enable_grabber(unsigned int id) virtual void on_enable_grabber(unsigned int id)
{ {
if ((0 <= id) && (id < 3)) if ((0 <= id) && (id < 3))
@ -113,17 +113,17 @@ protected:
if ((0 <= id) && (id < 3)) if ((0 <= id) && (id < 3))
m_gizmos[id].disable_grabber(0); m_gizmos[id].disable_grabber(0);
} }
virtual void on_start_dragging(const GLCanvas3D::Selection& selection); virtual void on_start_dragging(const Selection& selection);
virtual void on_stop_dragging(); virtual void on_stop_dragging();
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) virtual void on_update(const UpdateData& data, const Selection& selection)
{ {
for (GLGizmoRotate& g : m_gizmos) for (GLGizmoRotate& g : m_gizmos)
{ {
g.update(data, selection); g.update(data, selection);
} }
} }
virtual void on_render(const GLCanvas3D::Selection& selection) const; virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const virtual void on_render_for_picking(const Selection& selection) const
{ {
for (const GLGizmoRotate& g : m_gizmos) for (const GLGizmoRotate& g : m_gizmos)
{ {
@ -131,7 +131,7 @@ protected:
} }
} }
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection);
}; };

View File

@ -51,7 +51,7 @@ std::string GLGizmoScale3D::on_get_name() const
return L("Scale [S]"); return L("Scale [S]");
} }
void GLGizmoScale3D::on_start_dragging(const GLCanvas3D::Selection& selection) void GLGizmoScale3D::on_start_dragging(const Selection& selection)
{ {
if (m_hover_id != -1) if (m_hover_id != -1)
{ {
@ -60,7 +60,7 @@ void GLGizmoScale3D::on_start_dragging(const GLCanvas3D::Selection& selection)
} }
} }
void GLGizmoScale3D::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) void GLGizmoScale3D::on_update(const UpdateData& data, const Selection& selection)
{ {
if ((m_hover_id == 0) || (m_hover_id == 1)) if ((m_hover_id == 0) || (m_hover_id == 1))
do_scale_x(data); do_scale_x(data);
@ -72,7 +72,7 @@ void GLGizmoScale3D::on_update(const UpdateData& data, const GLCanvas3D::Selecti
do_scale_uniform(data); do_scale_uniform(data);
} }
void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const void GLGizmoScale3D::on_render(const Selection& selection) const
{ {
bool single_instance = selection.is_single_full_instance(); bool single_instance = selection.is_single_full_instance();
bool single_volume = selection.is_single_modifier() || selection.is_single_volume(); bool single_volume = selection.is_single_modifier() || selection.is_single_volume();
@ -121,7 +121,7 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
if (single_instance) if (single_instance)
{ {
// calculate bounding box in instance local reference system // calculate bounding box in instance local reference system
const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); const Selection::IndicesList& idxs = selection.get_volume_idxs();
for (unsigned int idx : idxs) for (unsigned int idx : idxs)
{ {
const GLVolume* vol = selection.get_volume(idx); const GLVolume* vol = selection.get_volume(idx);
@ -267,14 +267,14 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
} }
} }
void GLGizmoScale3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const void GLGizmoScale3D::on_render_for_picking(const Selection& selection) const
{ {
::glDisable(GL_DEPTH_TEST); ::glDisable(GL_DEPTH_TEST);
render_grabbers_for_picking(selection.get_bounding_box()); render_grabbers_for_picking(selection.get_bounding_box());
} }
void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
{ {
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
bool single_instance = selection.is_single_full_instance(); bool single_instance = selection.is_single_full_instance();

View File

@ -37,12 +37,12 @@ public:
protected: protected:
virtual bool on_init(); virtual bool on_init();
virtual std::string on_get_name() const; virtual std::string on_get_name() const;
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); } virtual bool on_is_activable(const Selection& selection) const { return !selection.is_wipe_tower(); }
virtual void on_start_dragging(const GLCanvas3D::Selection& selection); virtual void on_start_dragging(const Selection& selection);
virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); virtual void on_update(const UpdateData& data, const Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const; virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; virtual void on_render_for_picking(const Selection& selection) const;
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection);
private: private:
void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const; void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const;

View File

@ -42,7 +42,7 @@ bool GLGizmoSlaSupports::on_init()
return true; return true;
} }
void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection) void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const Selection& selection)
{ {
m_starting_center = Vec3d::Zero(); m_starting_center = Vec3d::Zero();
m_old_model_object = m_model_object; m_old_model_object = m_model_object;
@ -72,7 +72,7 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const G
} }
} }
void GLGizmoSlaSupports::on_render(const GLCanvas3D::Selection& selection) const void GLGizmoSlaSupports::on_render(const Selection& selection) const
{ {
::glEnable(GL_BLEND); ::glEnable(GL_BLEND);
::glEnable(GL_DEPTH_TEST); ::glEnable(GL_DEPTH_TEST);
@ -123,14 +123,14 @@ void GLGizmoSlaSupports::render_selection_rectangle() const
::glPopAttrib(); // restore former MatrixMode ::glPopAttrib(); // restore former MatrixMode
} }
void GLGizmoSlaSupports::on_render_for_picking(const GLCanvas3D::Selection& selection) const void GLGizmoSlaSupports::on_render_for_picking(const Selection& selection) const
{ {
::glEnable(GL_DEPTH_TEST); ::glEnable(GL_DEPTH_TEST);
render_points(selection, true); render_points(selection, true);
} }
void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, bool picking) const void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) const
{ {
if (m_quadric == nullptr || !selection.is_from_single_instance()) if (m_quadric == nullptr || !selection.is_from_single_instance())
return; return;
@ -201,12 +201,12 @@ void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, b
const float cone_height = 0.75f; const float cone_height = 0.75f;
::glPushMatrix(); ::glPushMatrix();
::glTranslatef(0.f, 0.f, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale); ::glTranslatef(0.f, 0.f, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale);
::gluCylinder(m_quadric, 0.f, cone_radius, cone_height, 36, 1); ::gluCylinder(m_quadric, 0.f, cone_radius, cone_height, 24, 1);
::glTranslatef(0.f, 0.f, cone_height); ::glTranslatef(0.f, 0.f, cone_height);
::gluDisk(m_quadric, 0.0, cone_radius, 36, 1); ::gluDisk(m_quadric, 0.0, cone_radius, 24, 1);
::glPopMatrix(); ::glPopMatrix();
} }
::gluSphere(m_quadric, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale, 64, 36); ::gluSphere(m_quadric, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale, 24, 12);
::glPopMatrix(); ::glPopMatrix();
} }
@ -276,7 +276,7 @@ std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse
igl::Hit hit; igl::Hit hit;
const GLCanvas3D::Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
double z_offset = volume->get_sla_shift_z(); double z_offset = volume->get_sla_shift_z();
@ -380,7 +380,7 @@ bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mous
GLdouble projection_matrix[16]; GLdouble projection_matrix[16];
::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix); ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix);
const GLCanvas3D::Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
double z_offset = volume->get_sla_shift_z(); double z_offset = volume->get_sla_shift_z();
@ -484,7 +484,7 @@ void GLGizmoSlaSupports::delete_selected_points(bool force)
//m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); //m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }
void GLGizmoSlaSupports::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) void GLGizmoSlaSupports::on_update(const UpdateData& data, const Selection& selection)
{ {
if (m_editing_mode && m_hover_id != -1 && data.mouse_pos && (!m_editing_mode_cache[m_hover_id].support_point.is_new_island || !m_lock_unique_islands)) { if (m_editing_mode && m_hover_id != -1 && data.mouse_pos && (!m_editing_mode_cache[m_hover_id].support_point.is_new_island || !m_lock_unique_islands)) {
std::pair<Vec3f, Vec3f> pos_and_normal; std::pair<Vec3f, Vec3f> pos_and_normal;
@ -542,7 +542,7 @@ void GLGizmoSlaSupports::update_cache_entry_normal(unsigned int i) const
void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
{ {
if (!m_model_object) if (!m_model_object)
return; return;
@ -686,14 +686,14 @@ RENDER_AGAIN:
m_parent.set_as_dirty(); m_parent.set_as_dirty();
} }
bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection) const bool GLGizmoSlaSupports::on_is_activable(const Selection& selection) const
{ {
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA
|| !selection.is_from_single_instance()) || !selection.is_from_single_instance())
return false; return false;
// Check that none of the selected volumes is outside. // Check that none of the selected volumes is outside.
const GLCanvas3D::Selection::IndicesList& list = selection.get_volume_idxs(); const Selection::IndicesList& list = selection.get_volume_idxs();
for (const auto& idx : list) for (const auto& idx : list)
if (selection.get_volume(idx)->is_outside) if (selection.get_volume(idx)->is_outside)
return false; return false;
@ -750,7 +750,7 @@ void GLGizmoSlaSupports::on_set_state()
void GLGizmoSlaSupports::on_start_dragging(const GLCanvas3D::Selection& selection) void GLGizmoSlaSupports::on_start_dragging(const Selection& selection)
{ {
if (m_hover_id != -1) { if (m_hover_id != -1) {
select_point(NoPoints); select_point(NoPoints);

View File

@ -58,19 +58,19 @@ public:
GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id); GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id);
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
virtual ~GLGizmoSlaSupports(); virtual ~GLGizmoSlaSupports();
void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection); void set_sla_support_data(ModelObject* model_object, const Selection& selection);
bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down); bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
void delete_selected_points(bool force = false); void delete_selected_points(bool force = false);
std::pair<float, float> get_sla_clipping_plane() const; std::pair<float, float> get_sla_clipping_plane() const;
private: private:
bool on_init(); bool on_init();
void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); void on_update(const UpdateData& data, const Selection& selection);
virtual void on_render(const GLCanvas3D::Selection& selection) const; virtual void on_render(const Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; virtual void on_render_for_picking(const Selection& selection) const;
void render_selection_rectangle() const; void render_selection_rectangle() const;
void render_points(const GLCanvas3D::Selection& selection, bool picking = false) const; void render_points(const Selection& selection, bool picking = false) const;
bool is_mesh_update_necessary() const; bool is_mesh_update_necessary() const;
void update_mesh(); void update_mesh();
void update_cache_entry_normal(unsigned int i) const; void update_cache_entry_normal(unsigned int i) const;
@ -113,11 +113,11 @@ private:
protected: protected:
void on_set_state() override; void on_set_state() override;
void on_start_dragging(const GLCanvas3D::Selection& selection) override; void on_start_dragging(const Selection& selection) override;
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) override; virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection) override;
virtual std::string on_get_name() const; virtual std::string on_get_name() const;
virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const; virtual bool on_is_activable(const Selection& selection) const;
virtual bool on_is_selectable() const; virtual bool on_is_selectable() const;
}; };

View File

@ -47,6 +47,7 @@
#include "MainFrame.hpp" #include "MainFrame.hpp"
#include "3DScene.hpp" #include "3DScene.hpp"
#include "GLCanvas3D.hpp" #include "GLCanvas3D.hpp"
#include "Selection.hpp"
#include "GLToolbar.hpp" #include "GLToolbar.hpp"
#include "GUI_Preview.hpp" #include "GUI_Preview.hpp"
#include "3DBed.hpp" #include "3DBed.hpp"
@ -1198,8 +1199,8 @@ struct Plater::priv
std::vector<size_t> load_model_objects(const ModelObjectPtrs &model_objects); std::vector<size_t> load_model_objects(const ModelObjectPtrs &model_objects);
std::unique_ptr<CheckboxFileDialog> get_export_file(GUI::FileType file_type); std::unique_ptr<CheckboxFileDialog> get_export_file(GUI::FileType file_type);
const GLCanvas3D::Selection& get_selection() const; const Selection& get_selection() const;
GLCanvas3D::Selection& get_selection(); Selection& get_selection();
int get_selected_object_idx() const; int get_selected_object_idx() const;
int get_selected_volume_idx() const; int get_selected_volume_idx() const;
void selection_changed(); void selection_changed();
@ -1271,6 +1272,15 @@ struct Plater::priv
// Sets m_bed.m_polygon to limit the object placement. // Sets m_bed.m_polygon to limit the object placement.
void set_bed_shape(const Pointfs& shape); void set_bed_shape(const Pointfs& shape);
bool can_delete() const;
bool can_delete_all() const;
bool can_increase_instances() const;
bool can_decrease_instances() const;
bool can_split_to_objects() const;
bool can_split_to_volumes() const;
bool can_arrange() const;
bool can_layers_editing() const;
private: private:
bool init_object_menu(); bool init_object_menu();
bool init_common_menu(wxMenu* menu, const bool is_part = false); bool init_common_menu(wxMenu* menu, const bool is_part = false);
@ -1279,16 +1289,9 @@ private:
bool complit_init_part_menu(); bool complit_init_part_menu();
void init_view_toolbar(); void init_view_toolbar();
bool can_delete_object() const;
bool can_increase_instances() const;
bool can_decrease_instances() const;
bool can_set_instance_to_object() const; bool can_set_instance_to_object() const;
bool can_split_to_objects() const;
bool can_split_to_volumes() const;
bool can_split() const; bool can_split() const;
bool layers_height_allowed() const; bool layers_height_allowed() const;
bool can_delete_all() const;
bool can_arrange() const;
bool can_mirror() const; bool can_mirror() const;
void update_fff_scene(); void update_fff_scene();
@ -1669,7 +1672,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
// automatic selection of added objects // automatic selection of added objects
if (!obj_idxs.empty() && (view3D != nullptr)) if (!obj_idxs.empty() && (view3D != nullptr))
{ {
GLCanvas3D::Selection& selection = view3D->get_canvas3d()->get_selection(); Selection& selection = view3D->get_canvas3d()->get_selection();
selection.clear(); selection.clear();
for (size_t idx : obj_idxs) for (size_t idx : obj_idxs)
{ {
@ -1818,12 +1821,12 @@ std::unique_ptr<CheckboxFileDialog> Plater::priv::get_export_file(GUI::FileType
return dlg; return dlg;
} }
const GLCanvas3D::Selection& Plater::priv::get_selection() const const Selection& Plater::priv::get_selection() const
{ {
return view3D->get_canvas3d()->get_selection(); return view3D->get_canvas3d()->get_selection();
} }
GLCanvas3D::Selection& Plater::priv::get_selection() Selection& Plater::priv::get_selection()
{ {
return view3D->get_canvas3d()->get_selection(); return view3D->get_canvas3d()->get_selection();
} }
@ -1848,12 +1851,6 @@ int Plater::priv::get_selected_volume_idx() const
void Plater::priv::selection_changed() void Plater::priv::selection_changed()
{ {
view3D->enable_toolbar_item("delete", can_delete_object());
view3D->enable_toolbar_item("more", can_increase_instances());
view3D->enable_toolbar_item("fewer", can_decrease_instances());
view3D->enable_toolbar_item("splitobjects", can_split());
view3D->enable_toolbar_item("splitvolumes", printer_technology == ptFFF && can_split());
// if the selection is not valid to allow for layer editing, we need to turn off the tool if it is running // if the selection is not valid to allow for layer editing, we need to turn off the tool if it is running
bool enable_layer_editing = layers_height_allowed(); bool enable_layer_editing = layers_height_allowed();
if (!enable_layer_editing && view3D->is_layers_editing_enabled()) { if (!enable_layer_editing && view3D->is_layers_editing_enabled()) {
@ -1861,18 +1858,12 @@ void Plater::priv::selection_changed()
on_action_layersediting(evt); on_action_layersediting(evt);
} }
view3D->enable_toolbar_item("layersediting", enable_layer_editing);
// forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears) // forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears)
view3D->render(); view3D->render();
} }
void Plater::priv::object_list_changed() void Plater::priv::object_list_changed()
{ {
// Enable/disable buttons depending on whether there are any objects on the platter.
view3D->enable_toolbar_item("deleteall", can_delete_all());
view3D->enable_toolbar_item("arrange", can_arrange());
const bool export_in_progress = this->background_process.is_export_scheduled(); // || ! send_gcode_file.empty()); const bool export_in_progress = this->background_process.is_export_scheduled(); // || ! send_gcode_file.empty());
// XXX: is this right? // XXX: is this right?
const bool model_fits = view3D->check_volumes_outside_state() == ModelInstance::PVS_Inside; const bool model_fits = view3D->check_volumes_outside_state() == ModelInstance::PVS_Inside;
@ -1951,9 +1942,6 @@ void Plater::priv::arrange()
wxBusyCursor wait; wxBusyCursor wait;
// Disable the arrange button (to prevent reentrancies, we will call wxYied)
view3D->enable_toolbar_item("arrange", can_arrange());
this->background_process.stop(); this->background_process.stop();
unsigned count = 0; unsigned count = 0;
for(auto obj : model.objects) count += obj->instances.size(); for(auto obj : model.objects) count += obj->instances.size();
@ -2024,9 +2012,6 @@ void Plater::priv::arrange()
statusbar()->set_cancel_callback(); // remove cancel button statusbar()->set_cancel_callback(); // remove cancel button
arranging.store(false); arranging.store(false);
// We enable back the arrange button
view3D->enable_toolbar_item("arrange", can_arrange());
// Do a full refresh of scene tree, including regenerating all the GLVolumes. // Do a full refresh of scene tree, including regenerating all the GLVolumes.
//FIXME The update function shall just reload the modified matrices. //FIXME The update function shall just reload the modified matrices.
update(true); update(true);
@ -2587,10 +2572,6 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
void Plater::priv::on_layer_editing_toggled(bool enable) void Plater::priv::on_layer_editing_toggled(bool enable)
{ {
view3D->enable_layers_editing(enable); view3D->enable_layers_editing(enable);
if (enable && !view3D->is_layers_editing_enabled()) {
// Initialization of the OpenGL shaders failed. Disable the tool.
view3D->enable_toolbar_item("layersediting", false);
}
view3D->set_as_dirty(); view3D->set_as_dirty();
} }
@ -2612,10 +2593,7 @@ void Plater::priv::on_action_split_volumes(SimpleEvent&)
void Plater::priv::on_action_layersediting(SimpleEvent&) void Plater::priv::on_action_layersediting(SimpleEvent&)
{ {
bool enable = !view3D->is_layers_editing_enabled(); view3D->enable_layers_editing(!view3D->is_layers_editing_enabled());
view3D->enable_layers_editing(enable);
if (enable && !view3D->is_layers_editing_enabled())
view3D->enable_toolbar_item("layersediting", false);
} }
void Plater::priv::on_object_select(SimpleEvent& evt) void Plater::priv::on_object_select(SimpleEvent& evt)
@ -2775,7 +2753,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
if (q != nullptr) if (q != nullptr)
{ {
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId());
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete->GetId());
} }
return true; return true;
@ -2880,7 +2858,7 @@ void Plater::priv::init_view_toolbar()
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
item.tooltip = GUI::L_str("3D editor view") + " [" + GUI::shortkey_ctrl_prefix() + "5]"; item.tooltip = GUI::L_str("3D editor view") + " [" + GUI::shortkey_ctrl_prefix() + "5]";
item.sprite_id = 0; item.sprite_id = 0;
item.action_event = EVT_GLVIEWTOOLBAR_3D; item.action_callback = [this]() { if (this->q != nullptr) wxPostEvent(this->q, SimpleEvent(EVT_GLVIEWTOOLBAR_3D)); };
item.is_toggable = false; item.is_toggable = false;
if (!view_toolbar.add_item(item)) if (!view_toolbar.add_item(item))
return; return;
@ -2891,57 +2869,21 @@ void Plater::priv::init_view_toolbar()
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
item.tooltip = GUI::L_str("Preview") + " [" + GUI::shortkey_ctrl_prefix() + "6]"; item.tooltip = GUI::L_str("Preview") + " [" + GUI::shortkey_ctrl_prefix() + "6]";
item.sprite_id = 1; item.sprite_id = 1;
item.action_event = EVT_GLVIEWTOOLBAR_PREVIEW; item.action_callback = [this]() { if (this->q != nullptr) wxPostEvent(this->q, SimpleEvent(EVT_GLVIEWTOOLBAR_PREVIEW)); };
item.is_toggable = false; item.is_toggable = false;
if (!view_toolbar.add_item(item)) if (!view_toolbar.add_item(item))
return; return;
view_toolbar.enable_item("3D");
view_toolbar.enable_item("Preview");
view_toolbar.select_item("3D"); view_toolbar.select_item("3D");
view_toolbar.set_enabled(true); view_toolbar.set_enabled(true);
} }
bool Plater::priv::can_delete_object() const
{
int obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
}
bool Plater::priv::can_increase_instances() const
{
int obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
}
bool Plater::priv::can_set_instance_to_object() const bool Plater::priv::can_set_instance_to_object() const
{ {
const int obj_idx = get_selected_object_idx(); const int obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1); return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1);
} }
bool Plater::priv::can_decrease_instances() const
{
int obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1);
}
bool Plater::priv::can_split_to_objects() const
{
int obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts();
}
bool Plater::priv::can_split_to_volumes() const
{
if (printer_technology == ptSLA)
return false;
// int obj_idx = get_selected_object_idx();
// return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts();
return sidebar->obj_list()->is_splittable();
}
bool Plater::priv::can_split() const bool Plater::priv::can_split() const
{ {
return sidebar->obj_list()->is_splittable(); return sidebar->obj_list()->is_splittable();
@ -2953,16 +2895,6 @@ bool Plater::priv::layers_height_allowed() const
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && config->opt_bool("variable_layer_height") && view3D->is_layers_editing_allowed(); return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && config->opt_bool("variable_layer_height") && view3D->is_layers_editing_allowed();
} }
bool Plater::priv::can_delete_all() const
{
return !model.objects.empty();
}
bool Plater::priv::can_arrange() const
{
return !model.objects.empty() && !arranging.load();
}
bool Plater::priv::can_mirror() const bool Plater::priv::can_mirror() const
{ {
return get_selection().is_from_single_instance(); return get_selection().is_from_single_instance();
@ -2978,11 +2910,51 @@ void Plater::priv::set_bed_shape(const Pointfs& shape)
} }
} }
bool Plater::priv::can_delete() const
{
return !get_selection().is_empty();
}
bool Plater::priv::can_delete_all() const
{
return !model.objects.empty();
}
bool Plater::priv::can_increase_instances() const
{
int obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
}
bool Plater::priv::can_decrease_instances() const
{
int obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1);
}
bool Plater::priv::can_split_to_objects() const
{
return can_split();
}
bool Plater::priv::can_split_to_volumes() const
{
return (printer_technology != ptSLA) && can_split();
}
bool Plater::priv::can_arrange() const
{
return !model.objects.empty() && !arranging.load();
}
bool Plater::priv::can_layers_editing() const
{
return layers_height_allowed();
}
void Plater::priv::update_object_menu() void Plater::priv::update_object_menu()
{ {
sidebar->obj_list()->append_menu_items_add_volume(&object_menu); sidebar->obj_list()->append_menu_items_add_volume(&object_menu);
if (view3D != nullptr)
view3D->update_toolbar_items_visibility();
} }
void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const
@ -3465,13 +3437,9 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
} }
else if(opt_key == "variable_layer_height") { else if(opt_key == "variable_layer_height") {
if (p->config->opt_bool("variable_layer_height") != true) { if (p->config->opt_bool("variable_layer_height") != true) {
p->view3D->enable_toolbar_item("layersediting", false);
p->view3D->enable_layers_editing(false); p->view3D->enable_layers_editing(false);
p->view3D->set_as_dirty(); p->view3D->set_as_dirty();
} }
else if (p->view3D->is_layers_editing_allowed()) {
p->view3D->enable_toolbar_item("layersediting", true);
}
} }
else if(opt_key == "extruder_colour") { else if(opt_key == "extruder_colour") {
update_scheduled = true; update_scheduled = true;
@ -3593,4 +3561,13 @@ void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/)
void Plater::update_object_menu() { p->update_object_menu(); } void Plater::update_object_menu() { p->update_object_menu(); }
bool Plater::can_delete() const { return p->can_delete(); }
bool Plater::can_delete_all() const { return p->can_delete_all(); }
bool Plater::can_increase_instances() const { return p->can_increase_instances(); }
bool Plater::can_decrease_instances() const { return p->can_decrease_instances(); }
bool Plater::can_split_to_objects() const { return p->can_split_to_objects(); }
bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); }
bool Plater::can_arrange() const { return p->can_arrange(); }
bool Plater::can_layers_editing() const { return p->can_layers_editing(); }
}} // namespace Slic3r::GUI }} // namespace Slic3r::GUI

View File

@ -178,6 +178,15 @@ public:
PrinterTechnology printer_technology() const; PrinterTechnology printer_technology() const;
void set_printer_technology(PrinterTechnology printer_technology); void set_printer_technology(PrinterTechnology printer_technology);
bool can_delete() const;
bool can_delete_all() const;
bool can_increase_instances() const;
bool can_decrease_instances() const;
bool can_split_to_objects() const;
bool can_split_to_volumes() const;
bool can_arrange() const;
bool can_layers_editing() const;
private: private:
struct priv; struct priv;
std::unique_ptr<priv> p; std::unique_ptr<priv> p;

1670
src/slic3r/GUI/Selection.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,301 @@
#ifndef slic3r_GUI_Selection_hpp_
#define slic3r_GUI_Selection_hpp_
#include <set>
#include "libslic3r/Geometry.hpp"
#include "3DScene.hpp"
namespace Slic3r {
namespace GUI {
class TransformationType
{
public:
enum Enum {
// Transforming in a world coordinate system
World = 0,
// Transforming in a local coordinate system
Local = 1,
// Absolute transformations, allowed in local coordinate system only.
Absolute = 0,
// Relative transformations, allowed in both local and world coordinate system.
Relative = 2,
// For group selection, the transformation is performed as if the group made a single solid body.
Joint = 0,
// For group selection, the transformation is performed on each object independently.
Independent = 4,
World_Relative_Joint = World | Relative | Joint,
World_Relative_Independent = World | Relative | Independent,
Local_Absolute_Joint = Local | Absolute | Joint,
Local_Absolute_Independent = Local | Absolute | Independent,
Local_Relative_Joint = Local | Relative | Joint,
Local_Relative_Independent = Local | Relative | Independent,
};
TransformationType() : m_value(World) {}
TransformationType(Enum value) : m_value(value) {}
TransformationType& operator=(Enum value) { m_value = value; return *this; }
Enum operator()() const { return m_value; }
bool has(Enum v) const { return ((unsigned int)m_value & (unsigned int)v) != 0; }
void set_world() { this->remove(Local); }
void set_local() { this->add(Local); }
void set_absolute() { this->remove(Relative); }
void set_relative() { this->add(Relative); }
void set_joint() { this->remove(Independent); }
void set_independent() { this->add(Independent); }
bool world() const { return !this->has(Local); }
bool local() const { return this->has(Local); }
bool absolute() const { return !this->has(Relative); }
bool relative() const { return this->has(Relative); }
bool joint() const { return !this->has(Independent); }
bool independent() const { return this->has(Independent); }
private:
void add(Enum v) { m_value = Enum((unsigned int)m_value | (unsigned int)v); }
void remove(Enum v) { m_value = Enum((unsigned int)m_value & (~(unsigned int)v)); }
Enum m_value;
};
class Selection
{
public:
typedef std::set<unsigned int> IndicesList;
enum EMode : unsigned char
{
Volume,
Instance
};
enum EType : unsigned char
{
Invalid,
Empty,
WipeTower,
SingleModifier,
MultipleModifier,
SingleVolume,
MultipleVolume,
SingleFullObject,
MultipleFullObject,
SingleFullInstance,
MultipleFullInstance,
Mixed
};
private:
struct VolumeCache
{
private:
struct TransformCache
{
Vec3d position;
Vec3d rotation;
Vec3d scaling_factor;
Vec3d mirror;
Transform3d rotation_matrix;
Transform3d scale_matrix;
Transform3d mirror_matrix;
Transform3d full_matrix;
TransformCache();
explicit TransformCache(const Geometry::Transformation& transform);
};
TransformCache m_volume;
TransformCache m_instance;
public:
VolumeCache() {}
VolumeCache(const Geometry::Transformation& volume_transform, const Geometry::Transformation& instance_transform);
const Vec3d& get_volume_position() const { return m_volume.position; }
const Vec3d& get_volume_rotation() const { return m_volume.rotation; }
const Vec3d& get_volume_scaling_factor() const { return m_volume.scaling_factor; }
const Vec3d& get_volume_mirror() const { return m_volume.mirror; }
const Transform3d& get_volume_rotation_matrix() const { return m_volume.rotation_matrix; }
const Transform3d& get_volume_scale_matrix() const { return m_volume.scale_matrix; }
const Transform3d& get_volume_mirror_matrix() const { return m_volume.mirror_matrix; }
const Transform3d& get_volume_full_matrix() const { return m_volume.full_matrix; }
const Vec3d& get_instance_position() const { return m_instance.position; }
const Vec3d& get_instance_rotation() const { return m_instance.rotation; }
const Vec3d& get_instance_scaling_factor() const { return m_instance.scaling_factor; }
const Vec3d& get_instance_mirror() const { return m_instance.mirror; }
const Transform3d& get_instance_rotation_matrix() const { return m_instance.rotation_matrix; }
const Transform3d& get_instance_scale_matrix() const { return m_instance.scale_matrix; }
const Transform3d& get_instance_mirror_matrix() const { return m_instance.mirror_matrix; }
const Transform3d& get_instance_full_matrix() const { return m_instance.full_matrix; }
};
typedef std::map<unsigned int, VolumeCache> VolumesCache;
typedef std::set<int> InstanceIdxsList;
typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap;
struct Cache
{
// Cache of GLVolume derived transformation matrices, valid during mouse dragging.
VolumesCache volumes_data;
// Center of the dragged selection, valid during mouse dragging.
Vec3d dragging_center;
// Map from indices of ModelObject instances in Model::objects
// to a set of indices of ModelVolume instances in ModelObject::instances
// Here the index means a position inside the respective std::vector, not ModelID.
ObjectIdxsToInstanceIdxsMap content;
};
// Volumes owned by GLCanvas3D.
GLVolumePtrs* m_volumes;
// Model, not owned.
Model* m_model;
bool m_valid;
EMode m_mode;
EType m_type;
// set of indices to m_volumes
IndicesList m_list;
Cache m_cache;
mutable BoundingBoxf3 m_bounding_box;
mutable bool m_bounding_box_dirty;
#if ENABLE_RENDER_SELECTION_CENTER
GLUquadricObj* m_quadric;
#endif // ENABLE_RENDER_SELECTION_CENTER
mutable GLArrow m_arrow;
mutable GLCurvedArrow m_curved_arrow;
mutable float m_scale_factor;
public:
Selection();
#if ENABLE_RENDER_SELECTION_CENTER
~Selection();
#endif // ENABLE_RENDER_SELECTION_CENTER
void set_volumes(GLVolumePtrs* volumes);
bool init(bool useVBOs);
Model* get_model() const { return m_model; }
void set_model(Model* model);
EMode get_mode() const { return m_mode; }
void set_mode(EMode mode) { m_mode = mode; }
void add(unsigned int volume_idx, bool as_single_selection = true);
void remove(unsigned int volume_idx);
void add_object(unsigned int object_idx, bool as_single_selection = true);
void remove_object(unsigned int object_idx);
void add_instance(unsigned int object_idx, unsigned int instance_idx, bool as_single_selection = true);
void remove_instance(unsigned int object_idx, unsigned int instance_idx);
void add_volume(unsigned int object_idx, unsigned int volume_idx, int instance_idx, bool as_single_selection = true);
void remove_volume(unsigned int object_idx, unsigned int volume_idx);
void add_all();
// Update the selection based on the map from old indices to new indices after m_volumes changed.
// If the current selection is by instance, this call may select newly added volumes, if they belong to already selected instances.
void volumes_changed(const std::vector<size_t> &map_volume_old_to_new);
void clear();
bool is_empty() const { return m_type == Empty; }
bool is_wipe_tower() const { return m_type == WipeTower; }
bool is_modifier() const { return (m_type == SingleModifier) || (m_type == MultipleModifier); }
bool is_single_modifier() const { return m_type == SingleModifier; }
bool is_multiple_modifier() const { return m_type == MultipleModifier; }
bool is_single_full_instance() const;
bool is_multiple_full_instance() const { return m_type == MultipleFullInstance; }
bool is_single_full_object() const { return m_type == SingleFullObject; }
bool is_multiple_full_object() const { return m_type == MultipleFullObject; }
bool is_single_volume() const { return m_type == SingleVolume; }
bool is_multiple_volume() const { return m_type == MultipleVolume; }
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;
bool contains_volume(unsigned int volume_idx) const { return std::find(m_list.begin(), m_list.end(), volume_idx) != m_list.end(); }
bool requires_uniform_scale() const;
// Returns the the object id if the selection is from a single object, otherwise is -1
int get_object_idx() const;
// Returns the instance id if the selection is from a single object and from a single instance, otherwise is -1
int get_instance_idx() const;
// Returns the indices of selected instances.
// Can only be called if selection is from a single object.
const InstanceIdxsList& get_instance_idxs() const;
const IndicesList& get_volume_idxs() const { return m_list; }
const GLVolume* get_volume(unsigned int volume_idx) const;
const ObjectIdxsToInstanceIdxsMap& get_content() const { return m_cache.content; }
unsigned int volumes_count() const { return (unsigned int)m_list.size(); }
const BoundingBoxf3& get_bounding_box() const;
void start_dragging();
void translate(const Vec3d& displacement, bool local = false);
void rotate(const Vec3d& rotation, TransformationType transformation_type);
void flattening_rotate(const Vec3d& normal);
void scale(const Vec3d& scale, bool local);
void mirror(Axis axis);
void translate(unsigned int object_idx, const Vec3d& displacement);
void translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement);
void erase();
void render(float scale_factor = 1.0) const;
#if ENABLE_RENDER_SELECTION_CENTER
void render_center() const;
#endif // ENABLE_RENDER_SELECTION_CENTER
void render_sidebar_hints(const std::string& sidebar_field) const;
bool requires_local_axes() const;
private:
void _update_valid();
void _update_type();
void _set_caches();
void _add_volume(unsigned int volume_idx);
void _add_instance(unsigned int object_idx, unsigned int instance_idx);
void _add_object(unsigned int object_idx);
void _remove_volume(unsigned int volume_idx);
void _remove_instance(unsigned int object_idx, unsigned int instance_idx);
void _remove_object(unsigned int object_idx);
void _calc_bounding_box() const;
void _render_selected_volumes() const;
void _render_synchronized_volumes() const;
void _render_bounding_box(const BoundingBoxf3& box, float* color) const;
void _render_sidebar_position_hints(const std::string& sidebar_field) const;
void _render_sidebar_rotation_hints(const std::string& sidebar_field) const;
void _render_sidebar_scale_hints(const std::string& sidebar_field) const;
void _render_sidebar_size_hints(const std::string& sidebar_field) const;
void _render_sidebar_position_hint(Axis axis) const;
void _render_sidebar_rotation_hint(Axis axis) const;
void _render_sidebar_scale_hint(Axis axis) const;
void _render_sidebar_size_hint(Axis axis, double length) const;
enum SyncRotationType {
// Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
SYNC_ROTATION_NONE = 0,
// Synchronize fully. Used from "place on bed" feature.
SYNC_ROTATION_FULL = 1,
// Synchronize after rotation by an axis not parallel with Z.
SYNC_ROTATION_GENERAL = 2,
};
void _synchronize_unselected_instances(SyncRotationType sync_rotation_type);
void _synchronize_unselected_volumes();
void _ensure_on_bed();
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GUI_Selection_hpp_