Merge branch 'master' of https://github.com/prusa3d/Slic3r into objects_centering
This commit is contained in:
commit
9a5d7a98a6
9 changed files with 130 additions and 32 deletions
|
@ -11,6 +11,7 @@
|
||||||
#include "../libslic3r.h"
|
#include "../libslic3r.h"
|
||||||
#include "../BoundingBox.hpp"
|
#include "../BoundingBox.hpp"
|
||||||
#include "../PrintConfig.hpp"
|
#include "../PrintConfig.hpp"
|
||||||
|
#include "../Utils.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ struct FillParams
|
||||||
// in this case we don't try to make more continuous paths
|
// in this case we don't try to make more continuous paths
|
||||||
bool complete;
|
bool complete;
|
||||||
};
|
};
|
||||||
static_assert(std::is_trivially_copyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");
|
static_assert(IsTriviallyCopyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");
|
||||||
|
|
||||||
class Fill
|
class Fill
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "libslic3r.h"
|
#include "libslic3r.h"
|
||||||
|
#include "Utils.hpp"
|
||||||
namespace Slic3r
|
namespace Slic3r
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ struct SlicingParameters
|
||||||
coordf_t object_print_z_min;
|
coordf_t object_print_z_min;
|
||||||
coordf_t object_print_z_max;
|
coordf_t object_print_z_max;
|
||||||
};
|
};
|
||||||
static_assert(std::is_trivially_copyable<SlicingParameters>::value, "SlicingParameters class is not POD (and it should be - see constructor).");
|
static_assert(IsTriviallyCopyable<SlicingParameters>::value, "SlicingParameters class is not POD (and it should be - see constructor).");
|
||||||
|
|
||||||
|
|
||||||
// The two slicing parameters lead to the same layering as long as the variable layer thickness is not in action.
|
// The two slicing parameters lead to the same layering as long as the variable layer thickness is not in action.
|
||||||
|
|
|
@ -159,6 +159,16 @@ template<class T> size_t next_highest_power_of_2(T v,
|
||||||
extern std::string xml_escape(std::string text);
|
extern std::string xml_escape(std::string text);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined __GNUC__ & __GNUC__ < 5
|
||||||
|
// Older GCCs don't have std::is_trivially_copyable
|
||||||
|
// cf. https://gcc.gnu.org/onlinedocs/gcc-4.9.4/libstdc++/manual/manual/status.html#status.iso.2011
|
||||||
|
#warning "GCC version < 5, faking std::is_trivially_copyable"
|
||||||
|
template<typename T> struct IsTriviallyCopyable { static constexpr bool value = true; };
|
||||||
|
#else
|
||||||
|
template<typename T> struct IsTriviallyCopyable : public std::is_trivially_copyable<T> {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class ScopeGuard
|
class ScopeGuard
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -856,6 +856,14 @@ bool GLCanvas3D::LayersEditing::init(const std::string& vertex_shader_filename,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::LayersEditing::set_config(const DynamicPrintConfig* config)
|
||||||
|
{
|
||||||
|
m_config = config;
|
||||||
|
delete m_slicing_parameters;
|
||||||
|
m_slicing_parameters = nullptr;
|
||||||
|
m_layers_texture.valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id)
|
void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id)
|
||||||
{
|
{
|
||||||
const ModelObject *model_object_new = (object_id >= 0) ? model.objects[object_id] : nullptr;
|
const ModelObject *model_object_new = (object_id >= 0) ? model.objects[object_id] : nullptr;
|
||||||
|
@ -864,6 +872,7 @@ void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id)
|
||||||
m_layer_height_profile_modified = false;
|
m_layer_height_profile_modified = false;
|
||||||
delete m_slicing_parameters;
|
delete m_slicing_parameters;
|
||||||
m_slicing_parameters = nullptr;
|
m_slicing_parameters = nullptr;
|
||||||
|
m_layers_texture.valid = false;
|
||||||
}
|
}
|
||||||
this->last_object_id = object_id;
|
this->last_object_id = object_id;
|
||||||
m_model_object = model_object_new;
|
m_model_object = model_object_new;
|
||||||
|
@ -1167,6 +1176,13 @@ void GLCanvas3D::LayersEditing::adjust_layer_height_profile()
|
||||||
m_layers_texture.valid = false;
|
m_layers_texture.valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::LayersEditing::reset_layer_height_profile()
|
||||||
|
{
|
||||||
|
const_cast<ModelObject*>(m_model_object)->layer_height_profile.clear();
|
||||||
|
m_layer_height_profile.clear();
|
||||||
|
m_layers_texture.valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas3D::LayersEditing::generate_layer_height_texture()
|
void GLCanvas3D::LayersEditing::generate_layer_height_texture()
|
||||||
{
|
{
|
||||||
this->update_slicing_parameters();
|
this->update_slicing_parameters();
|
||||||
|
@ -5024,7 +5040,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||||
if (evt.LeftDown())
|
if (evt.LeftDown())
|
||||||
{
|
{
|
||||||
// A volume is selected and the mouse is inside the reset button. Reset the ModelObject's layer height profile.
|
// A volume is selected and the mouse is inside the reset button. Reset the ModelObject's layer height profile.
|
||||||
m_model->objects[layer_editing_object_idx]->layer_height_profile.clear();
|
m_layers_editing.reset_layer_height_profile();
|
||||||
// Index 2 means no editing, just wait for mouse up event.
|
// Index 2 means no editing, just wait for mouse up event.
|
||||||
m_layers_editing.state = LayersEditing::Completed;
|
m_layers_editing.state = LayersEditing::Completed;
|
||||||
|
|
||||||
|
|
|
@ -346,7 +346,7 @@ class GLCanvas3D
|
||||||
~LayersEditing();
|
~LayersEditing();
|
||||||
|
|
||||||
bool init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename);
|
bool init(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename);
|
||||||
void set_config(const DynamicPrintConfig* config) { m_config = config; delete m_slicing_parameters; m_slicing_parameters = nullptr; }
|
void set_config(const DynamicPrintConfig* config);
|
||||||
void select_object(const Model &model, int object_id);
|
void select_object(const Model &model, int object_id);
|
||||||
|
|
||||||
bool is_allowed() const;
|
bool is_allowed() const;
|
||||||
|
@ -358,9 +358,9 @@ class GLCanvas3D
|
||||||
void render_overlay(const GLCanvas3D& canvas) const;
|
void render_overlay(const GLCanvas3D& canvas) const;
|
||||||
void render_volumes(const GLCanvas3D& canvas, const GLVolumeCollection& volumes) const;
|
void render_volumes(const GLCanvas3D& canvas, const GLVolumeCollection& volumes) const;
|
||||||
|
|
||||||
void generate_layer_height_texture();
|
|
||||||
void adjust_layer_height_profile();
|
void adjust_layer_height_profile();
|
||||||
void accept_changes(GLCanvas3D& canvas);
|
void accept_changes(GLCanvas3D& canvas);
|
||||||
|
void reset_layer_height_profile();
|
||||||
|
|
||||||
static float get_cursor_z_relative(const GLCanvas3D& canvas);
|
static float get_cursor_z_relative(const GLCanvas3D& canvas);
|
||||||
static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);
|
static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);
|
||||||
|
@ -374,6 +374,7 @@ class GLCanvas3D
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _is_initialized() const;
|
bool _is_initialized() const;
|
||||||
|
void generate_layer_height_texture();
|
||||||
void _render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const;
|
void _render_tooltip_texture(const GLCanvas3D& canvas, const Rect& bar_rect, const Rect& reset_rect) const;
|
||||||
void _render_reset_texture(const Rect& reset_rect) const;
|
void _render_reset_texture(const Rect& reset_rect) const;
|
||||||
void _render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const;
|
void _render_active_object_annotations(const GLCanvas3D& canvas, const Rect& bar_rect) const;
|
||||||
|
|
|
@ -97,7 +97,7 @@ void ObjectList::create_objects_ctrl()
|
||||||
// temporary workaround for the correct behavior of the Scrolled sidebar panel:
|
// temporary workaround for the correct behavior of the Scrolled sidebar panel:
|
||||||
// 1. set a height of the list to some big value
|
// 1. set a height of the list to some big value
|
||||||
// 2. change it to the normal min value (200) after first whole App updating/layouting
|
// 2. change it to the normal min value (200) after first whole App updating/layouting
|
||||||
SetMinSize(wxSize(-1, 1500)); // #ys_FIXME
|
SetMinSize(wxSize(-1, 3000)); // #ys_FIXME
|
||||||
|
|
||||||
m_sizer = new wxBoxSizer(wxVERTICAL);
|
m_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
m_sizer->Add(this, 1, wxGROW | wxLEFT, 20);
|
m_sizer->Add(this, 1, wxGROW | wxLEFT, 20);
|
||||||
|
@ -445,13 +445,21 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
|
||||||
|
|
||||||
// only allow drags for item, not containers
|
// only allow drags for item, not containers
|
||||||
if (multiple_selection() || GetSelection()!=item ||
|
if (multiple_selection() || GetSelection()!=item ||
|
||||||
m_objects_model->GetParent(item) == wxDataViewItem(0) ||
|
m_objects_model->GetParent(item) == wxDataViewItem(0)) {
|
||||||
m_objects_model->GetItemType(item) != itVolume ) {
|
event.Veto();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ItemType& type = m_objects_model->GetItemType(item);
|
||||||
|
if (!(type & (itVolume | itInstance))) {
|
||||||
event.Veto();
|
event.Veto();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dragged_data.init(m_objects_model->GetObjectIdByItem(item), m_objects_model->GetVolumeIdByItem(item));
|
m_dragged_data.init(m_objects_model->GetObjectIdByItem(item),
|
||||||
|
type&itVolume ? m_objects_model->GetVolumeIdByItem(item) :
|
||||||
|
m_objects_model->GetInstanceIdByItem(item),
|
||||||
|
type);
|
||||||
|
|
||||||
/* Under MSW or OSX, DnD moves an item to the place of another selected item
|
/* Under MSW or OSX, DnD moves an item to the place of another selected item
|
||||||
* But under GTK, DnD moves an item between another two items.
|
* But under GTK, DnD moves an item between another two items.
|
||||||
|
@ -470,31 +478,41 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
|
||||||
event.SetDragFlags(wxDrag_DefaultMove); // allows both copy and move;
|
event.SetDragFlags(wxDrag_DefaultMove); // allows both copy and move;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ObjectList::can_drop(const wxDataViewItem& item) const
|
||||||
|
{
|
||||||
|
return m_dragged_data.type() == itInstance && !item.IsOk() ||
|
||||||
|
m_dragged_data.type() == itVolume && item.IsOk() &&
|
||||||
|
m_objects_model->GetItemType(item) == itVolume &&
|
||||||
|
m_dragged_data.obj_idx() == m_objects_model->GetObjectIdByItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectList::OnDropPossible(wxDataViewEvent &event)
|
void ObjectList::OnDropPossible(wxDataViewEvent &event)
|
||||||
{
|
{
|
||||||
wxDataViewItem item(event.GetItem());
|
const wxDataViewItem& item = event.GetItem();
|
||||||
|
|
||||||
// only allow drags for item or background, not containers
|
if (!can_drop(item))
|
||||||
if (!item.IsOk() ||
|
|
||||||
m_objects_model->GetParent(item) == wxDataViewItem(0) ||
|
|
||||||
m_objects_model->GetItemType(item) != itVolume ||
|
|
||||||
m_dragged_data.obj_idx() != m_objects_model->GetObjectIdByItem(item))
|
|
||||||
event.Veto();
|
event.Veto();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectList::OnDrop(wxDataViewEvent &event)
|
void ObjectList::OnDrop(wxDataViewEvent &event)
|
||||||
{
|
{
|
||||||
wxDataViewItem item(event.GetItem());
|
const wxDataViewItem& item = event.GetItem();
|
||||||
|
|
||||||
if (!item.IsOk() || m_objects_model->GetParent(item) == wxDataViewItem(0) ||
|
if (!can_drop(item))
|
||||||
m_objects_model->GetItemType(item) != itVolume ||
|
{
|
||||||
m_dragged_data.obj_idx() != m_objects_model->GetObjectIdByItem(item)) {
|
|
||||||
event.Veto();
|
event.Veto();
|
||||||
m_dragged_data.clear();
|
m_dragged_data.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int from_volume_id = m_dragged_data.vol_idx();
|
if (m_dragged_data.type() == itInstance)
|
||||||
|
{
|
||||||
|
instance_to_separated_object(m_dragged_data.obj_idx(), m_dragged_data.sub_obj_idx());
|
||||||
|
m_dragged_data.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int from_volume_id = m_dragged_data.sub_obj_idx();
|
||||||
int to_volume_id = m_objects_model->GetVolumeIdByItem(item);
|
int to_volume_id = m_objects_model->GetVolumeIdByItem(item);
|
||||||
|
|
||||||
// It looks like a fixed in current version of the wxWidgets
|
// It looks like a fixed in current version of the wxWidgets
|
||||||
|
@ -506,7 +524,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
|
||||||
// if (to_volume_id > from_volume_id) to_volume_id--;
|
// if (to_volume_id > from_volume_id) to_volume_id--;
|
||||||
// #endif // __WXGTK__
|
// #endif // __WXGTK__
|
||||||
|
|
||||||
auto& volumes = (*m_objects)[/*m_selected_object_id*/m_dragged_data.obj_idx()]->volumes;
|
auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes;
|
||||||
auto delta = to_volume_id < from_volume_id ? -1 : 1;
|
auto delta = to_volume_id < from_volume_id ? -1 : 1;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++)
|
for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++)
|
||||||
|
@ -516,7 +534,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
|
||||||
m_objects_model->GetParent(item)));
|
m_objects_model->GetParent(item)));
|
||||||
|
|
||||||
m_parts_changed = true;
|
m_parts_changed = true;
|
||||||
parts_changed(/*m_selected_object_id*/m_dragged_data.obj_idx());
|
parts_changed(m_dragged_data.obj_idx());
|
||||||
|
|
||||||
m_dragged_data.clear();
|
m_dragged_data.clear();
|
||||||
}
|
}
|
||||||
|
@ -1733,6 +1751,25 @@ void ObjectList::update_settings_items()
|
||||||
UnselectAll();
|
UnselectAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjectList::instance_to_separated_object(const int obj_idx, const int inst_idx)
|
||||||
|
{
|
||||||
|
// create new object from selected instance
|
||||||
|
ModelObject* model_object = (*m_objects)[obj_idx]->get_model()->add_object(*(*m_objects)[obj_idx]);
|
||||||
|
for (int i = model_object->instances.size() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (i == inst_idx)
|
||||||
|
continue;
|
||||||
|
model_object->delete_instance(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new object to the object_list
|
||||||
|
add_object_to_list(m_objects->size() - 1);
|
||||||
|
|
||||||
|
// delete selected instance from the object
|
||||||
|
del_subobject_from_object(obj_idx, inst_idx, itInstance);
|
||||||
|
delete_instance_from_list(obj_idx, inst_idx);
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectList::ItemValueChanged(wxDataViewEvent &event)
|
void ObjectList::ItemValueChanged(wxDataViewEvent &event)
|
||||||
{
|
{
|
||||||
if (event.GetColumn() == 0)
|
if (event.GetColumn() == 0)
|
||||||
|
|
|
@ -56,22 +56,27 @@ class ObjectList : public wxDataViewCtrl
|
||||||
|
|
||||||
struct dragged_item_data
|
struct dragged_item_data
|
||||||
{
|
{
|
||||||
void init(const int obj_idx, const int vol_idx) {
|
void init(const int obj_idx, const int subobj_idx, const ItemType type) {
|
||||||
m_obj_idx = obj_idx;
|
m_obj_idx = obj_idx;
|
||||||
m_vol_idx = vol_idx;
|
m_subobj_idx = subobj_idx;
|
||||||
|
m_type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
m_obj_idx = -1;
|
m_obj_idx = -1;
|
||||||
m_vol_idx = -1;
|
m_subobj_idx = -1;
|
||||||
|
m_type = itUndef;
|
||||||
}
|
}
|
||||||
|
|
||||||
int obj_idx() const { return m_obj_idx; }
|
int obj_idx() const { return m_obj_idx; }
|
||||||
int vol_idx() const { return m_vol_idx; }
|
int sub_obj_idx() const { return m_subobj_idx; }
|
||||||
|
ItemType type() const { return m_type; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_obj_idx = -1;
|
int m_obj_idx = -1;
|
||||||
int m_vol_idx = -1;
|
int m_subobj_idx = -1;
|
||||||
|
ItemType m_type = itUndef;
|
||||||
|
|
||||||
} m_dragged_data;
|
} m_dragged_data;
|
||||||
|
|
||||||
wxBoxSizer *m_sizer {nullptr};
|
wxBoxSizer *m_sizer {nullptr};
|
||||||
|
@ -222,6 +227,8 @@ public:
|
||||||
bool has_multi_part_objects();
|
bool has_multi_part_objects();
|
||||||
void update_settings_items();
|
void update_settings_items();
|
||||||
|
|
||||||
|
void instance_to_separated_object(const int obj_idx, const int inst_idx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnChar(wxKeyEvent& event);
|
void OnChar(wxKeyEvent& event);
|
||||||
void OnContextMenu(wxDataViewEvent &event);
|
void OnContextMenu(wxDataViewEvent &event);
|
||||||
|
@ -229,6 +236,7 @@ private:
|
||||||
void OnBeginDrag(wxDataViewEvent &event);
|
void OnBeginDrag(wxDataViewEvent &event);
|
||||||
void OnDropPossible(wxDataViewEvent &event);
|
void OnDropPossible(wxDataViewEvent &event);
|
||||||
void OnDrop(wxDataViewEvent &event);
|
void OnDrop(wxDataViewEvent &event);
|
||||||
|
bool can_drop(const wxDataViewItem& item) const ;
|
||||||
|
|
||||||
void ItemValueChanged(wxDataViewEvent &event);
|
void ItemValueChanged(wxDataViewEvent &event);
|
||||||
void OnEditingDone(wxDataViewEvent &event);
|
void OnEditingDone(wxDataViewEvent &event);
|
||||||
|
|
|
@ -1066,6 +1066,7 @@ private:
|
||||||
bool can_delete_object() const;
|
bool can_delete_object() const;
|
||||||
bool can_increase_instances() const;
|
bool can_increase_instances() const;
|
||||||
bool can_decrease_instances() const;
|
bool can_decrease_instances() const;
|
||||||
|
bool can_set_instance_to_object() const;
|
||||||
bool can_split_to_objects() const;
|
bool can_split_to_objects() const;
|
||||||
bool can_split_to_volumes() const;
|
bool can_split_to_volumes() const;
|
||||||
bool can_split() const;
|
bool can_split() const;
|
||||||
|
@ -2378,11 +2379,17 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
|
||||||
[this](wxCommandEvent&) { q->decrease_instances(); }, "delete.png");
|
[this](wxCommandEvent&) { q->decrease_instances(); }, "delete.png");
|
||||||
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of copies")) + dots, _(L("Change the number of copies of the selected object")),
|
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of copies")) + dots, _(L("Change the number of copies of the selected object")),
|
||||||
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "textfield.png");
|
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "textfield.png");
|
||||||
|
|
||||||
|
menu->AppendSeparator();
|
||||||
|
wxMenuItem* item_instance_to_object = append_menu_item(menu, wxID_ANY, _(L("Set as a Separated Object")) + dots, _(L("Set an Instance as a Separate Object")),
|
||||||
|
[this](wxCommandEvent&) { q->instance_to_separated_object(); }, "");
|
||||||
|
|
||||||
if (q != nullptr)
|
if (q != nullptr)
|
||||||
{
|
{
|
||||||
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId());
|
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId());
|
||||||
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId());
|
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId());
|
||||||
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_set_number_of_copies->GetId());
|
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_set_number_of_copies->GetId());
|
||||||
|
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_set_instance_to_object()); }, item_instance_to_object->GetId());
|
||||||
}
|
}
|
||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
|
|
||||||
|
@ -2445,9 +2452,9 @@ bool Plater::priv::complit_init_object_menu()
|
||||||
// ui updates needs to be binded to the parent panel
|
// ui updates needs to be binded to the parent panel
|
||||||
if (q != nullptr)
|
if (q != nullptr)
|
||||||
{
|
{
|
||||||
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split/*_to_objects() || can_split_to_volumes*/()); }, item_split->GetId());
|
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split->GetId());
|
||||||
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split/*_to_objects*/()); }, item_split_objects->GetId());
|
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split_objects->GetId());
|
||||||
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split/*_to_volumes*/()); }, item_split_volumes->GetId());
|
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split_volumes->GetId());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2466,7 +2473,7 @@ bool Plater::priv::complit_init_sla_object_menu()
|
||||||
// ui updates needs to be binded to the parent panel
|
// ui updates needs to be binded to the parent panel
|
||||||
if (q != nullptr)
|
if (q != nullptr)
|
||||||
{
|
{
|
||||||
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split/*_to_objects*/()); }, item_split->GetId());
|
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split->GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2485,7 +2492,7 @@ bool Plater::priv::complit_init_part_menu()
|
||||||
// ui updates needs to be binded to the parent panel
|
// ui updates needs to be binded to the parent panel
|
||||||
if (q != nullptr)
|
if (q != nullptr)
|
||||||
{
|
{
|
||||||
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split/*_to_volumes*/()); }, item_split->GetId());
|
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split->GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2553,6 +2560,12 @@ bool Plater::priv::can_increase_instances() const
|
||||||
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
|
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Plater::priv::can_set_instance_to_object() const
|
||||||
|
{
|
||||||
|
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_decrease_instances() const
|
bool Plater::priv::can_decrease_instances() const
|
||||||
{
|
{
|
||||||
int obj_idx = get_selected_object_idx();
|
int obj_idx = get_selected_object_idx();
|
||||||
|
@ -2779,6 +2792,16 @@ void Plater::set_number_of_copies(/*size_t num*/)
|
||||||
decrease_instances(-diff);
|
decrease_instances(-diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::instance_to_separated_object()
|
||||||
|
{
|
||||||
|
const int obj_idx = p->get_selected_object_idx();
|
||||||
|
const int inst_idx = p->get_selection().get_instance_idx();
|
||||||
|
if (obj_idx == -1 || inst_idx == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sidebar().obj_list()->instance_to_separated_object(obj_idx, inst_idx);
|
||||||
|
}
|
||||||
|
|
||||||
bool Plater::is_selection_empty() const
|
bool Plater::is_selection_empty() const
|
||||||
{
|
{
|
||||||
return p->get_selection().is_empty();
|
return p->get_selection().is_empty();
|
||||||
|
|
|
@ -136,6 +136,7 @@ public:
|
||||||
void increase_instances(size_t num = 1);
|
void increase_instances(size_t num = 1);
|
||||||
void decrease_instances(size_t num = 1);
|
void decrease_instances(size_t num = 1);
|
||||||
void set_number_of_copies(/*size_t num*/);
|
void set_number_of_copies(/*size_t num*/);
|
||||||
|
void instance_to_separated_object();
|
||||||
bool is_selection_empty() const;
|
bool is_selection_empty() const;
|
||||||
|
|
||||||
void cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false);
|
void cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false);
|
||||||
|
|
Loading…
Reference in a new issue