mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-04 04:24:04 -06:00
Merge remote-tracking branch 'origin/master' into tm_autoplacement
This commit is contained in:
commit
8c57541fe9
20 changed files with 338 additions and 110 deletions
|
@ -545,6 +545,11 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
|
|||
std::string model_path = resources_dir() + "/models/" + key;
|
||||
#endif // ENABLE_PRINT_BED_MODELS
|
||||
|
||||
#if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
|
||||
GLfloat max_anisotropy = 0.0f;
|
||||
::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy);
|
||||
#endif // ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
|
||||
|
||||
std::string filename = tex_path + "_top.png";
|
||||
if ((m_top_texture.get_id() == 0) || (m_top_texture.get_source() != filename))
|
||||
{
|
||||
|
@ -553,6 +558,14 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
|
|||
_render_custom();
|
||||
return;
|
||||
}
|
||||
#if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
|
||||
if (max_anisotropy > 0.0f)
|
||||
{
|
||||
::glBindTexture(GL_TEXTURE_2D, m_top_texture.get_id());
|
||||
::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
#endif // ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
|
||||
}
|
||||
|
||||
filename = tex_path + "_bottom.png";
|
||||
|
@ -563,6 +576,14 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
|
|||
_render_custom();
|
||||
return;
|
||||
}
|
||||
#if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
|
||||
if (max_anisotropy > 0.0f)
|
||||
{
|
||||
::glBindTexture(GL_TEXTURE_2D, m_bottom_texture.get_id());
|
||||
::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
#endif // ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
|
||||
}
|
||||
|
||||
#if ENABLE_PRINT_BED_MODELS
|
||||
|
@ -570,7 +591,7 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
|
|||
{
|
||||
filename = model_path + "_bed.stl";
|
||||
if ((m_model.get_filename() != filename) && m_model.init_from_file(filename, useVBOs))
|
||||
m_model.center_around(m_bounding_box.center() - Vec3d(0.0, 0.0, 1.0 + 0.5 * m_model.get_bounding_box().size()(2)));
|
||||
m_model.center_around(m_bounding_box.center() - Vec3d(0.0, 0.0, 0.1 + 0.5 * m_model.get_bounding_box().size()(2)));
|
||||
|
||||
if (!m_model.get_filename().empty())
|
||||
{
|
||||
|
@ -1179,11 +1200,12 @@ void GLCanvas3D::LayersEditing::adjust_layer_height_profile()
|
|||
m_layers_texture.valid = false;
|
||||
}
|
||||
|
||||
void GLCanvas3D::LayersEditing::reset_layer_height_profile()
|
||||
void GLCanvas3D::LayersEditing::reset_layer_height_profile(GLCanvas3D& canvas)
|
||||
{
|
||||
const_cast<ModelObject*>(m_model_object)->layer_height_profile.clear();
|
||||
m_layer_height_profile.clear();
|
||||
m_layers_texture.valid = false;
|
||||
canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||
}
|
||||
|
||||
void GLCanvas3D::LayersEditing::generate_layer_height_texture()
|
||||
|
@ -5117,7 +5139,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
if (evt.LeftDown())
|
||||
{
|
||||
// A volume is selected and the mouse is inside the reset button. Reset the ModelObject's layer height profile.
|
||||
m_layers_editing.reset_layer_height_profile();
|
||||
m_layers_editing.reset_layer_height_profile(*this);
|
||||
// Index 2 means no editing, just wait for mouse up event.
|
||||
m_layers_editing.state = LayersEditing::Completed;
|
||||
|
||||
|
@ -5251,7 +5273,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
if (m_volumes.volumes[m_hover_volume_id]->hover && !m_volumes.volumes[m_hover_volume_id]->is_wipe_tower)
|
||||
{
|
||||
// forces the selection of the volume
|
||||
m_selection.add(m_hover_volume_id);
|
||||
if (!m_selection.is_multiple_full_instance())
|
||||
m_selection.add(m_hover_volume_id);
|
||||
m_gizmos.update_on_off_state(m_selection);
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
|
||||
_update_gizmos_data();
|
||||
|
@ -5822,6 +5845,7 @@ void GLCanvas3D::set_camera_zoom(float zoom)
|
|||
void GLCanvas3D::update_gizmos_on_off_state()
|
||||
{
|
||||
set_as_dirty();
|
||||
_update_gizmos_data();
|
||||
m_gizmos.update_on_off_state(get_selection());
|
||||
}
|
||||
|
||||
|
|
|
@ -360,7 +360,7 @@ class GLCanvas3D
|
|||
|
||||
void adjust_layer_height_profile();
|
||||
void accept_changes(GLCanvas3D& canvas);
|
||||
void reset_layer_height_profile();
|
||||
void reset_layer_height_profile(GLCanvas3D& canvas);
|
||||
|
||||
static float get_cursor_z_relative(const GLCanvas3D& canvas);
|
||||
static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);
|
||||
|
|
|
@ -1511,7 +1511,7 @@ void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
|
|||
bool object_changed = m_model_object != model_object;
|
||||
m_model_object = model_object;
|
||||
|
||||
if (object_changed && is_plane_update_necessary())
|
||||
if (model_object && (object_changed || is_plane_update_necessary()))
|
||||
update_planes();
|
||||
}
|
||||
|
||||
|
@ -1585,15 +1585,17 @@ void GLGizmoFlatten::update_planes()
|
|||
m_planes.pop_back();
|
||||
}
|
||||
|
||||
// Let's prepare transformation of the normal vector from mesh to instance coordinates.
|
||||
Geometry::Transformation t(inst_matrix);
|
||||
Vec3d scaling = t.get_scaling_factor();
|
||||
t.set_scaling_factor(Vec3d(1./scaling(0), 1./scaling(1), 1./scaling(2)));
|
||||
|
||||
// Now we'll go through all the polygons, transform the points into xy plane to process them:
|
||||
for (unsigned int polygon_id=0; polygon_id < m_planes.size(); ++polygon_id) {
|
||||
Pointf3s& polygon = m_planes[polygon_id].vertices;
|
||||
const Vec3d& normal = m_planes[polygon_id].normal;
|
||||
|
||||
// let's transform the normal accodring to the instance matrix:
|
||||
Geometry::Transformation t(inst_matrix);
|
||||
Vec3d scaling = t.get_scaling_factor();
|
||||
t.set_scaling_factor(Vec3d(1./(scaling(0)*scaling(0)), 1./(scaling(0)*scaling(0)), 1./(scaling(0)*scaling(0))));
|
||||
// transform the normal according to the instance matrix:
|
||||
Vec3d normal_transformed = t.get_matrix() * normal;
|
||||
|
||||
// We are going to rotate about z and y to flatten the plane
|
||||
|
|
|
@ -194,6 +194,8 @@ bool GUI_App::OnInit()
|
|||
preset_updater->slic3r_update_notify();
|
||||
}
|
||||
preset_updater->sync(preset_bundle);
|
||||
|
||||
load_current_presets();
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ ObjectList::ObjectList(wxWindow* parent) :
|
|||
create_object_popupmenu(&m_menu_object);
|
||||
create_part_popupmenu(&m_menu_part);
|
||||
create_sla_object_popupmenu(&m_menu_sla_object);
|
||||
create_instance_popupmenu(&m_menu_instance);
|
||||
|
||||
// describe control behavior
|
||||
Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) {
|
||||
|
@ -97,7 +98,7 @@ void ObjectList::create_objects_ctrl()
|
|||
// temporary workaround for the correct behavior of the Scrolled sidebar panel:
|
||||
// 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
|
||||
SetMinSize(wxSize(-1, 1500)); // #ys_FIXME
|
||||
SetMinSize(wxSize(-1, 3000)); // #ys_FIXME
|
||||
|
||||
m_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
m_sizer->Add(this, 1, wxGROW | wxLEFT, 20);
|
||||
|
@ -400,15 +401,28 @@ void ObjectList::OnContextMenu(wxDataViewEvent&)
|
|||
|
||||
void ObjectList::show_context_menu()
|
||||
{
|
||||
if (multiple_selection() && selected_instances_of_same_object())
|
||||
{
|
||||
wxGetApp().plater()->PopupMenu(&m_menu_instance);
|
||||
|
||||
wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
|
||||
evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto item = GetSelection();
|
||||
if (item)
|
||||
{
|
||||
if (!(m_objects_model->GetItemType(item) & (itObject | itVolume)))
|
||||
const ItemType type = m_objects_model->GetItemType(item);
|
||||
if (!(type & (itObject | itVolume | itInstance)))
|
||||
return;
|
||||
wxMenu* menu = m_objects_model->GetParent(item) != wxDataViewItem(0) ? &m_menu_part :
|
||||
|
||||
wxMenu* menu = type & itInstance ? &m_menu_instance :
|
||||
m_objects_model->GetParent(item) != wxDataViewItem(0) ? &m_menu_part :
|
||||
wxGetApp().plater()->printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object;
|
||||
|
||||
append_menu_item_settings(menu);
|
||||
if (!(type & itInstance))
|
||||
append_menu_item_settings(menu);
|
||||
|
||||
wxGetApp().plater()->PopupMenu(menu);
|
||||
|
||||
|
@ -443,15 +457,35 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
|
|||
{
|
||||
const wxDataViewItem item(event.GetItem());
|
||||
|
||||
// only allow drags for item, not containers
|
||||
if (multiple_selection() || GetSelection()!=item ||
|
||||
m_objects_model->GetParent(item) == wxDataViewItem(0) ||
|
||||
m_objects_model->GetItemType(item) != itVolume ) {
|
||||
const bool mult_sel = multiple_selection();
|
||||
|
||||
if (mult_sel && !selected_instances_of_same_object() ||
|
||||
!mult_sel && (GetSelection() != item ||
|
||||
m_objects_model->GetParent(item) == wxDataViewItem(0) ) ) {
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
|
||||
const ItemType& type = m_objects_model->GetItemType(item);
|
||||
if (!(type & (itVolume | itInstance))) {
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
|
||||
m_dragged_data.init(m_objects_model->GetObjectIdByItem(item), m_objects_model->GetVolumeIdByItem(item));
|
||||
if (mult_sel)
|
||||
{
|
||||
m_dragged_data.init(m_objects_model->GetObjectIdByItem(item),type);
|
||||
std::set<int>& sub_obj_idxs = m_dragged_data.inst_idxs();
|
||||
wxDataViewItemArray sels;
|
||||
GetSelections(sels);
|
||||
for (auto sel : sels )
|
||||
sub_obj_idxs.insert(m_objects_model->GetInstanceIdByItem(sel));
|
||||
}
|
||||
else
|
||||
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
|
||||
* But under GTK, DnD moves an item between another two items.
|
||||
|
@ -470,31 +504,41 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
|
|||
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)
|
||||
{
|
||||
wxDataViewItem item(event.GetItem());
|
||||
const wxDataViewItem& item = event.GetItem();
|
||||
|
||||
// only allow drags for item or background, not containers
|
||||
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))
|
||||
if (!can_drop(item))
|
||||
event.Veto();
|
||||
}
|
||||
|
||||
void ObjectList::OnDrop(wxDataViewEvent &event)
|
||||
{
|
||||
wxDataViewItem item(event.GetItem());
|
||||
const wxDataViewItem& item = event.GetItem();
|
||||
|
||||
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)) {
|
||||
if (!can_drop(item))
|
||||
{
|
||||
event.Veto();
|
||||
m_dragged_data.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
const int from_volume_id = m_dragged_data.vol_idx();
|
||||
if (m_dragged_data.type() == itInstance)
|
||||
{
|
||||
instances_to_separated_object(m_dragged_data.obj_idx(), m_dragged_data.inst_idxs());
|
||||
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);
|
||||
|
||||
// It looks like a fixed in current version of the wxWidgets
|
||||
|
@ -506,7 +550,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
|
|||
// if (to_volume_id > from_volume_id) to_volume_id--;
|
||||
// #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;
|
||||
int cnt = 0;
|
||||
for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++)
|
||||
|
@ -516,7 +560,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
|
|||
m_objects_model->GetParent(item)));
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -741,6 +785,12 @@ wxMenuItem* ObjectList::append_menu_item_change_type(wxMenu* menu)
|
|||
|
||||
}
|
||||
|
||||
wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu)
|
||||
{
|
||||
return append_menu_item(menu, wxID_ANY, _(L("Set as a Separated Object")), "",
|
||||
[this](wxCommandEvent&) { split_instances(); }, "", menu);
|
||||
}
|
||||
|
||||
void ObjectList::create_object_popupmenu(wxMenu *menu)
|
||||
{
|
||||
append_menu_items_add_volume(menu);
|
||||
|
@ -769,6 +819,11 @@ void ObjectList::create_part_popupmenu(wxMenu *menu)
|
|||
menu->AppendSeparator();
|
||||
}
|
||||
|
||||
void ObjectList::create_instance_popupmenu(wxMenu*menu)
|
||||
{
|
||||
m_menu_item_split_instances = append_menu_item_instance_to_object(menu);
|
||||
}
|
||||
|
||||
wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu)
|
||||
{
|
||||
wxMenu *menu = new wxMenu;
|
||||
|
@ -1116,6 +1171,27 @@ bool ObjectList::is_splittable()
|
|||
return splittable;
|
||||
}
|
||||
|
||||
bool ObjectList::selected_instances_of_same_object()
|
||||
{
|
||||
wxDataViewItemArray sels;
|
||||
GetSelections(sels);
|
||||
|
||||
const int obj_idx = m_objects_model->GetObjectIdByItem(sels.front());
|
||||
|
||||
for (auto item : sels) {
|
||||
if (! (m_objects_model->GetItemType(item) & itInstance) ||
|
||||
obj_idx != m_objects_model->GetObjectIdByItem(item))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObjectList::can_split_instances()
|
||||
{
|
||||
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
return selection.is_multiple_full_instance() || selection.is_single_full_instance();
|
||||
}
|
||||
|
||||
void ObjectList::part_settings_changed()
|
||||
{
|
||||
m_part_settings_changed = true;
|
||||
|
@ -1419,7 +1495,7 @@ bool ObjectList::multiple_selection() const
|
|||
|
||||
void ObjectList::update_selections()
|
||||
{
|
||||
auto& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
wxDataViewItemArray sels;
|
||||
|
||||
// We doesn't update selection if SettingsItem for the current object/part is selected
|
||||
|
@ -1505,7 +1581,7 @@ void ObjectList::update_selections()
|
|||
|
||||
void ObjectList::update_selections_on_canvas()
|
||||
{
|
||||
auto& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
|
||||
const int sel_cnt = GetSelectedItemsCount();
|
||||
if (sel_cnt == 0) {
|
||||
|
@ -1729,6 +1805,43 @@ void ObjectList::update_settings_items()
|
|||
UnselectAll();
|
||||
}
|
||||
|
||||
void ObjectList::instances_to_separated_object(const int obj_idx, const std::set<int>& inst_idxs)
|
||||
{
|
||||
// create new object from selected instance
|
||||
ModelObject* model_object = (*m_objects)[obj_idx]->get_model()->add_object(*(*m_objects)[obj_idx]);
|
||||
for (int inst_idx = model_object->instances.size() - 1; inst_idx >= 0; inst_idx--)
|
||||
{
|
||||
if (find(inst_idxs.begin(), inst_idxs.end(), inst_idx) != inst_idxs.end())
|
||||
continue;
|
||||
model_object->delete_instance(inst_idx);
|
||||
}
|
||||
|
||||
// Add new object to the object_list
|
||||
add_object_to_list(m_objects->size() - 1);
|
||||
|
||||
for (std::set<int>::const_reverse_iterator it = inst_idxs.rbegin(); it != inst_idxs.rend(); ++it)
|
||||
{
|
||||
// delete selected instance from the object
|
||||
del_subobject_from_object(obj_idx, *it, itInstance);
|
||||
delete_instance_from_list(obj_idx, *it);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectList::split_instances()
|
||||
{
|
||||
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
const int obj_idx = selection.get_object_idx();
|
||||
if (obj_idx == -1)
|
||||
return;
|
||||
|
||||
const int inst_idx = selection.get_instance_idx();
|
||||
const std::set<int> inst_idxs = inst_idx < 0 ?
|
||||
selection.get_instance_idxs() :
|
||||
std::set<int>{ inst_idx };
|
||||
|
||||
instances_to_separated_object(obj_idx, inst_idxs);
|
||||
}
|
||||
|
||||
void ObjectList::ItemValueChanged(wxDataViewEvent &event)
|
||||
{
|
||||
if (event.GetColumn() == 0)
|
||||
|
|
|
@ -56,22 +56,38 @@ class ObjectList : public wxDataViewCtrl
|
|||
|
||||
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_vol_idx = vol_idx;
|
||||
m_type = type;
|
||||
if (m_type&itVolume)
|
||||
m_vol_idx = subobj_idx;
|
||||
else
|
||||
m_inst_idxs.insert(subobj_idx);
|
||||
}
|
||||
|
||||
void init(const int obj_idx, const ItemType type) {
|
||||
m_obj_idx = obj_idx;
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
m_obj_idx = -1;
|
||||
m_vol_idx = -1;
|
||||
m_vol_idx = -1;
|
||||
m_inst_idxs.clear();
|
||||
m_type = itUndef;
|
||||
}
|
||||
|
||||
int obj_idx() const { return m_obj_idx; }
|
||||
int vol_idx() const { return m_vol_idx; }
|
||||
int sub_obj_idx() const { return m_vol_idx; }
|
||||
ItemType type() const { return m_type; }
|
||||
std::set<int>& inst_idxs() { return m_inst_idxs; }
|
||||
|
||||
private:
|
||||
int m_obj_idx = -1;
|
||||
int m_vol_idx = -1;
|
||||
std::set<int> m_inst_idxs{};
|
||||
ItemType m_type = itUndef;
|
||||
|
||||
} m_dragged_data;
|
||||
|
||||
wxBoxSizer *m_sizer {nullptr};
|
||||
|
@ -91,9 +107,11 @@ class ObjectList : public wxDataViewCtrl
|
|||
wxMenu m_menu_object;
|
||||
wxMenu m_menu_part;
|
||||
wxMenu m_menu_sla_object;
|
||||
wxMenu m_menu_instance;
|
||||
wxMenuItem* m_menu_item_split { nullptr };
|
||||
wxMenuItem* m_menu_item_split_part { nullptr };
|
||||
wxMenuItem* m_menu_item_settings { nullptr };
|
||||
wxMenuItem* m_menu_item_split_instances { nullptr };
|
||||
|
||||
std::vector<wxBitmap*> m_bmp_vector;
|
||||
|
||||
|
@ -148,9 +166,11 @@ public:
|
|||
wxMenuItem* append_menu_item_split(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_settings(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_change_type(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu);
|
||||
void create_object_popupmenu(wxMenu *menu);
|
||||
void create_sla_object_popupmenu(wxMenu*menu);
|
||||
void create_part_popupmenu(wxMenu*menu);
|
||||
void create_instance_popupmenu(wxMenu*menu);
|
||||
wxMenu* create_settings_popupmenu(wxMenu *parent_menu);
|
||||
|
||||
void update_opt_keys(t_config_option_keys& t_optopt_keys);
|
||||
|
@ -166,6 +186,8 @@ public:
|
|||
void split();
|
||||
bool get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume);
|
||||
bool is_splittable();
|
||||
bool selected_instances_of_same_object();
|
||||
bool can_split_instances();
|
||||
|
||||
wxPoint get_mouse_position_in_control();
|
||||
wxBoxSizer* get_sizer() {return m_sizer;}
|
||||
|
@ -222,6 +244,9 @@ public:
|
|||
bool has_multi_part_objects();
|
||||
void update_settings_items();
|
||||
|
||||
void instances_to_separated_object(const int obj_idx, const std::set<int>& inst_idx);
|
||||
void split_instances();
|
||||
|
||||
private:
|
||||
void OnChar(wxKeyEvent& event);
|
||||
void OnContextMenu(wxDataViewEvent &event);
|
||||
|
@ -229,6 +254,7 @@ private:
|
|||
void OnBeginDrag(wxDataViewEvent &event);
|
||||
void OnDropPossible(wxDataViewEvent &event);
|
||||
void OnDrop(wxDataViewEvent &event);
|
||||
bool can_drop(const wxDataViewItem& item) const ;
|
||||
|
||||
void ItemValueChanged(wxDataViewEvent &event);
|
||||
void OnEditingDone(wxDataViewEvent &event);
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
#define _(s) Slic3r::GUI::I18N::translate((s))
|
||||
#endif /* _ */
|
||||
|
||||
#ifndef _CTX
|
||||
#define _CTX(s, ctx) Slic3r::GUI::I18N::translate((s), (ctx))
|
||||
#endif /* _ */
|
||||
|
||||
#ifndef L
|
||||
// !!! If you needed to translate some wxString,
|
||||
// !!! please use _(L(string))
|
||||
|
@ -21,6 +25,7 @@
|
|||
#define slic3r_GUI_I18N_hpp_
|
||||
|
||||
#include <wx/intl.h>
|
||||
#include <wx/version.h>
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
|
@ -29,7 +34,20 @@ namespace I18N {
|
|||
inline wxString translate(const wchar_t *s) { return wxGetTranslation(s); }
|
||||
inline wxString translate(const std::string &s) { return wxGetTranslation(wxString(s.c_str(), wxConvUTF8)); }
|
||||
inline wxString translate(const std::wstring &s) { return wxGetTranslation(s.c_str()); }
|
||||
}
|
||||
|
||||
#if wxCHECK_VERSION(3, 1, 1)
|
||||
#define _wxGetTranslation_ctx(S, CTX) wxGetTranslation((S), wxEmptyString, (CTX))
|
||||
#else
|
||||
#define _wxGetTranslation_ctx(S, CTX) ((void)(CTX), wxGetTranslation((S)))
|
||||
#endif
|
||||
|
||||
inline wxString translate(const char *s, const char* ctx) { return _wxGetTranslation_ctx(wxString(s, wxConvUTF8), ctx); }
|
||||
inline wxString translate(const wchar_t *s, const char* ctx) { return _wxGetTranslation_ctx(s, ctx); }
|
||||
inline wxString translate(const std::string &s, const char* ctx) { return _wxGetTranslation_ctx(wxString(s.c_str(), wxConvUTF8), ctx); }
|
||||
inline wxString translate(const std::wstring &s, const char* ctx) { return _wxGetTranslation_ctx(s.c_str(), ctx); }
|
||||
|
||||
#undef _wxGetTranslation_ctx
|
||||
}
|
||||
|
||||
// Return translated std::string as a wxString
|
||||
wxString L_str(const std::string &str);
|
||||
|
|
|
@ -155,7 +155,6 @@ void MainFrame::create_preset_tabs()
|
|||
add_created_tab(new TabSLAPrint(m_tabpanel));
|
||||
add_created_tab(new TabSLAMaterial(m_tabpanel));
|
||||
add_created_tab(new TabPrinter(m_tabpanel));
|
||||
GUI::wxGetApp().load_current_presets();
|
||||
}
|
||||
|
||||
void MainFrame::add_created_tab(Tab* panel)
|
||||
|
|
|
@ -234,7 +234,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n
|
|||
// wxString str_label = _(option.label);
|
||||
//! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
|
||||
wxString str_label = (option.label == "Top" || option.label == "Bottom") ?
|
||||
wxGETTEXT_IN_CONTEXT("Layers", wxString(option.label)) :
|
||||
_CTX(option.label, "Layers") :
|
||||
_(option.label);
|
||||
label = new wxStaticText(parent(), wxID_ANY, str_label + ":", wxDefaultPosition, wxDefaultSize);
|
||||
label->SetFont(label_font);
|
||||
|
|
|
@ -1063,6 +1063,7 @@ private:
|
|||
bool can_delete_object() const;
|
||||
bool can_increase_instances() const;
|
||||
bool can_decrease_instances() const;
|
||||
bool can_set_instance_to_object() const;
|
||||
bool can_split_to_objects() const;
|
||||
bool can_split_to_volumes() const;
|
||||
bool can_split() const;
|
||||
|
@ -2365,11 +2366,16 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
|
|||
[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")),
|
||||
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "textfield.png");
|
||||
|
||||
menu->AppendSeparator();
|
||||
wxMenuItem* item_instance_to_object = sidebar->obj_list()->append_menu_item_instance_to_object(menu);
|
||||
|
||||
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_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_set_instance_to_object()); }, item_instance_to_object->GetId());
|
||||
}
|
||||
menu->AppendSeparator();
|
||||
|
||||
|
@ -2432,9 +2438,9 @@ bool Plater::priv::complit_init_object_menu()
|
|||
// ui updates needs to be binded to the parent panel
|
||||
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/*_to_objects*/()); }, 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->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()); }, item_split_volumes->GetId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -2453,7 +2459,7 @@ bool Plater::priv::complit_init_sla_object_menu()
|
|||
// ui updates needs to be binded to the parent panel
|
||||
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;
|
||||
|
@ -2472,7 +2478,7 @@ bool Plater::priv::complit_init_part_menu()
|
|||
// ui updates needs to be binded to the parent panel
|
||||
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;
|
||||
|
@ -2540,6 +2546,12 @@ bool Plater::priv::can_increase_instances() const
|
|||
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
|
||||
{
|
||||
int obj_idx = get_selected_object_idx();
|
||||
|
|
|
@ -406,7 +406,7 @@ void PrusaObjectDataViewModelNode::set_object_action_icon() {
|
|||
m_action_icon = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("add_object.png")), wxBITMAP_TYPE_PNG);
|
||||
}
|
||||
void PrusaObjectDataViewModelNode::set_part_action_icon() {
|
||||
m_action_icon = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("cog.png")), wxBITMAP_TYPE_PNG);
|
||||
m_action_icon = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var(m_type == itVolume ? "cog.png" : "brick_go.png")), wxBITMAP_TYPE_PNG);
|
||||
}
|
||||
|
||||
Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr;
|
||||
|
|
|
@ -275,6 +275,7 @@ public:
|
|||
else if (type == itInstance) {
|
||||
m_idx = parent->GetChildCount();
|
||||
m_name = wxString::Format("Instance_%d", m_idx+1);
|
||||
set_part_action_icon();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue