WIP: Transformations of an instance in world coordinate system
from the side panel.
This commit is contained in:
parent
2088abdc31
commit
5d2537af35
@ -15,19 +15,7 @@ namespace Slic3r { namespace GUI {
|
|||||||
|
|
||||||
wxString double_to_string(double const value, const int max_precision /*= 4*/)
|
wxString double_to_string(double const value, const int max_precision /*= 4*/)
|
||||||
{
|
{
|
||||||
if (value - int(value) == 0)
|
return wxNumberFormatter::ToString(value, max_precision, wxNumberFormatter::Style_NoTrailingZeroes);
|
||||||
return wxString::Format(_T("%i"), int(value));
|
|
||||||
|
|
||||||
int precision = max_precision;
|
|
||||||
for (size_t p = 1; p < max_precision; p++)
|
|
||||||
{
|
|
||||||
double cur_val = pow(10, p)*value;
|
|
||||||
if (cur_val - int(cur_val) == 0) {
|
|
||||||
precision = p;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return wxNumberFormatter::ToString(value, precision, wxNumberFormatter::Style_None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Field::PostInitialize()
|
void Field::PostInitialize()
|
||||||
|
@ -57,16 +57,14 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
def.type = coString;
|
def.type = coString;
|
||||||
def.width = field_width/*50*/;
|
def.width = field_width/*50*/;
|
||||||
|
|
||||||
std::vector<std::string> axes{ "x", "y", "z" };
|
for (const std::string axis : { "x", "y", "z" }) {
|
||||||
for (const auto axis : axes) {
|
const std::string label = boost::algorithm::to_upper_copy(axis);
|
||||||
const auto label = boost::algorithm::to_upper_copy(axis);
|
|
||||||
def.default_value = new ConfigOptionString{ " " + label };
|
def.default_value = new ConfigOptionString{ " " + label };
|
||||||
Option option = Option(def, axis + "_axis_legend");
|
Option option = Option(def, axis + "_axis_legend");
|
||||||
line.append_option(option);
|
line.append_option(option);
|
||||||
}
|
}
|
||||||
m_og->append_line(line);
|
m_og->append_line(line);
|
||||||
|
|
||||||
|
|
||||||
auto add_og_to_object_settings = [this, field_width](const std::string& option_name, const std::string& sidetext)
|
auto add_og_to_object_settings = [this, field_width](const std::string& option_name, const std::string& sidetext)
|
||||||
{
|
{
|
||||||
Line line = { _(option_name), "" };
|
Line line = { _(option_name), "" };
|
||||||
@ -98,11 +96,10 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
|
|
||||||
const std::string lower_name = boost::algorithm::to_lower_copy(option_name);
|
const std::string lower_name = boost::algorithm::to_lower_copy(option_name);
|
||||||
|
|
||||||
std::vector<std::string> axes{ "x", "y", "z" };
|
for (const char *axis : { "_x", "_y", "_z" }) {
|
||||||
for (auto axis : axes) {
|
if (axis[1] == 'z')
|
||||||
if (axis == "z")
|
|
||||||
def.sidetext = sidetext;
|
def.sidetext = sidetext;
|
||||||
Option option = Option(def, lower_name + "_" + axis);
|
Option option = Option(def, lower_name + axis);
|
||||||
option.opt.full_width = true;
|
option.opt.full_width = true;
|
||||||
line.append_option(option);
|
line.append_option(option);
|
||||||
}
|
}
|
||||||
@ -162,7 +159,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||||||
m_new_scale_label_string = L("Scale factors");
|
m_new_scale_label_string = L("Scale factors");
|
||||||
|
|
||||||
ObjectList* obj_list = wxGetApp().obj_list();
|
ObjectList* obj_list = wxGetApp().obj_list();
|
||||||
if (selection.is_single_full_instance())
|
if (selection.is_single_full_instance() && ! m_world_coordinates)
|
||||||
{
|
{
|
||||||
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
|
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||||
@ -174,21 +171,26 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||||||
if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size()))
|
if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size()))
|
||||||
{
|
{
|
||||||
bool changed_box = false;
|
bool changed_box = false;
|
||||||
|
//FIXME matching an object idx may not be enough
|
||||||
if (!m_cache.instance.matches_object(obj_idx))
|
if (!m_cache.instance.matches_object(obj_idx))
|
||||||
{
|
{
|
||||||
m_cache.instance.set(obj_idx, instance_idx, (*wxGetApp().model_objects())[obj_idx]->raw_mesh_bounding_box().size());
|
m_cache.instance.set(obj_idx, instance_idx, (*wxGetApp().model_objects())[obj_idx]->raw_mesh_bounding_box().size());
|
||||||
changed_box = true;
|
changed_box = true;
|
||||||
}
|
}
|
||||||
|
//FIXME matching an instance idx may not be enough. Check for ModelObject id an all ModelVolume ids.
|
||||||
if (changed_box || !m_cache.instance.matches_instance(instance_idx) || !m_cache.scale.isApprox(100.0 * m_new_scale))
|
if (changed_box || !m_cache.instance.matches_instance(instance_idx) || !m_cache.scale.isApprox(100.0 * m_new_scale))
|
||||||
m_new_size = (volume->get_instance_transformation().get_matrix(true, true) * m_cache.instance.box_size).cwiseAbs();
|
m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct(m_cache.instance.box_size);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
// this should never happen
|
// this should never happen
|
||||||
|
assert(false);
|
||||||
m_new_size = Vec3d::Zero();
|
m_new_size = Vec3d::Zero();
|
||||||
|
}
|
||||||
|
|
||||||
m_new_enabled = true;
|
m_new_enabled = true;
|
||||||
}
|
}
|
||||||
else if (selection.is_single_full_object() && obj_list->is_selected(itObject))
|
else if ((selection.is_single_full_instance() && m_world_coordinates) ||
|
||||||
|
(selection.is_single_full_object() && obj_list->is_selected(itObject)))
|
||||||
{
|
{
|
||||||
m_cache.instance.reset();
|
m_cache.instance.reset();
|
||||||
|
|
||||||
@ -210,7 +212,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||||||
m_new_position = volume->get_volume_offset();
|
m_new_position = volume->get_volume_offset();
|
||||||
m_new_rotation = volume->get_volume_rotation();
|
m_new_rotation = volume->get_volume_rotation();
|
||||||
m_new_scale = volume->get_volume_scaling_factor();
|
m_new_scale = volume->get_volume_scaling_factor();
|
||||||
m_new_size = (volume->get_volume_transformation().get_matrix(true, true) * volume->bounding_box.size()).cwiseAbs();
|
m_new_size = volume->get_volume_transformation().get_scaling_factor().cwiseProduct(volume->bounding_box.size());
|
||||||
m_new_enabled = true;
|
m_new_enabled = true;
|
||||||
}
|
}
|
||||||
else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot))
|
else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot))
|
||||||
@ -222,8 +224,11 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||||||
m_new_size = selection.get_bounding_box().size();
|
m_new_size = selection.get_bounding_box().size();
|
||||||
m_new_enabled = true;
|
m_new_enabled = true;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
// No selection, reset the cache.
|
||||||
|
assert(selection.is_empty());
|
||||||
reset_settings_value();
|
reset_settings_value();
|
||||||
|
}
|
||||||
|
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
@ -233,73 +238,35 @@ void ObjectManipulation::update_if_dirty()
|
|||||||
if (!m_dirty)
|
if (!m_dirty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_cache.move_label_string != _(m_new_move_label_string)+ ":")
|
auto update_label = [](std::string &label_cache, const std::string &new_label, wxStaticText *widget) {
|
||||||
{
|
std::string new_label_localized = _(new_label) + ":";
|
||||||
m_cache.move_label_string = _(m_new_move_label_string)+ ":";
|
if (label_cache != new_label_localized) {
|
||||||
m_move_Label->SetLabel(m_cache.move_label_string);
|
label_cache = new_label_localized;
|
||||||
|
widget->SetLabel(new_label_localized);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
update_label(m_cache.move_label_string, m_new_move_label_string, m_move_Label);
|
||||||
|
update_label(m_cache.rotate_label_string, m_new_rotate_label_string, m_rotate_Label);
|
||||||
|
update_label(m_cache.scale_label_string, m_new_scale_label_string, m_scale_Label);
|
||||||
|
|
||||||
if (m_cache.rotate_label_string != _(m_new_rotate_label_string)+ ":")
|
Vec3d scale = m_new_scale * 100.0;
|
||||||
{
|
Vec3d deg_rotation = (180.0 / M_PI) * m_new_rotation;
|
||||||
m_cache.rotate_label_string = _(m_new_rotate_label_string)+ ":";
|
|
||||||
m_rotate_Label->SetLabel(m_cache.rotate_label_string);
|
char axis[2] = "x";
|
||||||
|
for (int i = 0; i < 3; ++ i, ++ axis[0]) {
|
||||||
|
if (m_cache.position(i) != m_new_position(i))
|
||||||
|
m_og->set_value(std::string("position_") + axis, double_to_string(m_new_position(i), 2));
|
||||||
|
if (m_cache.scale(i) != scale(i))
|
||||||
|
m_og->set_value(std::string("scale_") + axis, double_to_string(scale(i), 2));
|
||||||
|
if (m_cache.size(i) != m_new_size(i))
|
||||||
|
m_og->set_value(std::string("size_") + axis, double_to_string(m_new_size(i), 2));
|
||||||
|
if (m_cache.rotation(i) != m_new_rotation(i) || m_new_rotation(i) == 0.0)
|
||||||
|
m_og->set_value(std::string("rotation_") + axis, double_to_string(deg_rotation(i), 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cache.scale_label_string != _(m_new_scale_label_string)+ ":")
|
|
||||||
{
|
|
||||||
m_cache.scale_label_string = _(m_new_scale_label_string)+ ":";
|
|
||||||
m_scale_Label->SetLabel(m_cache.scale_label_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_cache.position(0) != m_new_position(0))
|
|
||||||
m_og->set_value("position_x", double_to_string(m_new_position(0), 2));
|
|
||||||
|
|
||||||
if (m_cache.position(1) != m_new_position(1))
|
|
||||||
m_og->set_value("position_y", double_to_string(m_new_position(1), 2));
|
|
||||||
|
|
||||||
if (m_cache.position(2) != m_new_position(2))
|
|
||||||
m_og->set_value("position_z", double_to_string(m_new_position(2), 2));
|
|
||||||
|
|
||||||
m_cache.position = m_new_position;
|
m_cache.position = m_new_position;
|
||||||
|
|
||||||
auto scale = m_new_scale * 100.0;
|
|
||||||
if (m_cache.scale(0) != scale(0))
|
|
||||||
m_og->set_value("scale_x", double_to_string(scale(0), 2));
|
|
||||||
|
|
||||||
if (m_cache.scale(1) != scale(1))
|
|
||||||
m_og->set_value("scale_y", double_to_string(scale(1), 2));
|
|
||||||
|
|
||||||
if (m_cache.scale(2) != scale(2))
|
|
||||||
m_og->set_value("scale_z", double_to_string(scale(2), 2));
|
|
||||||
|
|
||||||
m_cache.scale = scale;
|
m_cache.scale = scale;
|
||||||
|
|
||||||
if (m_cache.size(0) != m_new_size(0))
|
|
||||||
m_og->set_value("size_x", double_to_string(m_new_size(0), 2));
|
|
||||||
|
|
||||||
if (m_cache.size(1) != m_new_size(1))
|
|
||||||
m_og->set_value("size_y", double_to_string(m_new_size(1), 2));
|
|
||||||
|
|
||||||
if (m_cache.size(2) != m_new_size(2))
|
|
||||||
m_og->set_value("size_z", double_to_string(m_new_size(2), 2));
|
|
||||||
|
|
||||||
m_cache.size = m_new_size;
|
m_cache.size = m_new_size;
|
||||||
|
|
||||||
Vec3d deg_rotation;
|
|
||||||
for (size_t i = 0; i < 3; ++i)
|
|
||||||
{
|
|
||||||
deg_rotation(i) = Geometry::rad2deg(m_new_rotation(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_cache.rotation(0) != m_new_rotation(0)) || (m_new_rotation(0) == 0.0))
|
|
||||||
m_og->set_value("rotation_x", double_to_string(deg_rotation(0), 2));
|
|
||||||
|
|
||||||
if ((m_cache.rotation(1) != m_new_rotation(1)) || (m_new_rotation(1) == 0.0))
|
|
||||||
m_og->set_value("rotation_y", double_to_string(deg_rotation(1), 2));
|
|
||||||
|
|
||||||
if ((m_cache.rotation(2) != m_new_rotation(2)) || (m_new_rotation(2) == 0.0))
|
|
||||||
m_og->set_value("rotation_z", double_to_string(deg_rotation(2), 2));
|
|
||||||
|
|
||||||
m_cache.rotation = deg_rotation;
|
m_cache.rotation = deg_rotation;
|
||||||
|
|
||||||
if (wxGetApp().plater()->canvas3D()->get_selection().requires_uniform_scale()) {
|
if (wxGetApp().plater()->canvas3D()->get_selection().requires_uniform_scale()) {
|
||||||
@ -361,23 +328,21 @@ 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 Selection& selection = canvas->get_selection();
|
Selection& selection = canvas->get_selection();
|
||||||
|
|
||||||
TransformationType transformation_type(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() && ! m_world_coordinates) {
|
||||||
//FIXME 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3d rad_rotation;
|
selection.start_dragging();
|
||||||
for (size_t i = 0; i < 3; ++i)
|
selection.rotate(
|
||||||
rad_rotation(i) = Geometry::deg2rad((transformation_type.absolute()) ? rotation(i) : rotation(i) - m_cache.rotation(i));
|
(M_PI / 180.0) * (transformation_type.absolute() ? rotation : rotation - m_cache.rotation),
|
||||||
|
transformation_type);
|
||||||
canvas->get_selection().start_dragging();
|
|
||||||
canvas->get_selection().rotate(rad_rotation, transformation_type);
|
|
||||||
canvas->do_rotate();
|
canvas->do_rotate();
|
||||||
|
|
||||||
m_cache.rotation = rotation;
|
m_cache.rotation = rotation;
|
||||||
@ -385,32 +350,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;
|
this->do_scale(scale);
|
||||||
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
|
||||||
if (m_uniform_scale || selection.requires_uniform_scale())
|
|
||||||
{
|
|
||||||
Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs();
|
|
||||||
double max_diff = abs_scale_diff(X);
|
|
||||||
Axis max_diff_axis = X;
|
|
||||||
if (max_diff < abs_scale_diff(Y))
|
|
||||||
{
|
|
||||||
max_diff = abs_scale_diff(Y);
|
|
||||||
max_diff_axis = Y;
|
|
||||||
}
|
|
||||||
if (max_diff < abs_scale_diff(Z))
|
|
||||||
{
|
|
||||||
max_diff = abs_scale_diff(Z);
|
|
||||||
max_diff_axis = Z;
|
|
||||||
}
|
|
||||||
scaling_factor = scale(max_diff_axis) * Vec3d::Ones();
|
|
||||||
}
|
|
||||||
|
|
||||||
scaling_factor *= 0.01;
|
|
||||||
|
|
||||||
auto canvas = wxGetApp().plater()->canvas3D();
|
|
||||||
canvas->get_selection().start_dragging();
|
|
||||||
canvas->get_selection().scale(scaling_factor, false);
|
|
||||||
canvas->do_scale();
|
|
||||||
|
|
||||||
if (!m_cache.scale.isApprox(scale))
|
if (!m_cache.scale.isApprox(scale))
|
||||||
m_cache.instance.instance_idx = -1;
|
m_cache.instance.instance_idx = -1;
|
||||||
@ -428,41 +368,35 @@ void ObjectManipulation::change_size_value(const Vec3d& size)
|
|||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||||
ref_size = volume->bounding_box.size();
|
ref_size = volume->bounding_box.size();
|
||||||
}
|
}
|
||||||
else if (selection.is_single_full_instance())
|
else if (selection.is_single_full_instance() && ! m_world_coordinates)
|
||||||
ref_size = m_cache.instance.box_size;
|
ref_size = m_cache.instance.box_size;
|
||||||
|
|
||||||
Vec3d scale = 100.0 * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2));
|
this->do_scale(100.0 * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2)));
|
||||||
Vec3d scaling_factor = scale;
|
|
||||||
|
|
||||||
if (m_uniform_scale || selection.requires_uniform_scale())
|
|
||||||
{
|
|
||||||
Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs();
|
|
||||||
double max_diff = abs_scale_diff(X);
|
|
||||||
Axis max_diff_axis = X;
|
|
||||||
if (max_diff < abs_scale_diff(Y))
|
|
||||||
{
|
|
||||||
max_diff = abs_scale_diff(Y);
|
|
||||||
max_diff_axis = Y;
|
|
||||||
}
|
|
||||||
if (max_diff < abs_scale_diff(Z))
|
|
||||||
{
|
|
||||||
max_diff = abs_scale_diff(Z);
|
|
||||||
max_diff_axis = Z;
|
|
||||||
}
|
|
||||||
scaling_factor = scale(max_diff_axis) * Vec3d::Ones();
|
|
||||||
}
|
|
||||||
|
|
||||||
scaling_factor *= 0.01;
|
|
||||||
|
|
||||||
auto canvas = wxGetApp().plater()->canvas3D();
|
|
||||||
canvas->get_selection().start_dragging();
|
|
||||||
canvas->get_selection().scale(scaling_factor, false);
|
|
||||||
canvas->do_scale();
|
|
||||||
|
|
||||||
m_cache.size = size;
|
m_cache.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectManipulation::on_change(const t_config_option_key& opt_key, const boost::any& value)
|
void ObjectManipulation::do_scale(const Vec3d &scale) const
|
||||||
|
{
|
||||||
|
Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||||
|
Vec3d scaling_factor = scale;
|
||||||
|
|
||||||
|
if (m_uniform_scale || selection.requires_uniform_scale())
|
||||||
|
{
|
||||||
|
int max_diff_axis;
|
||||||
|
(scale - m_cache.scale).cwiseAbs().maxCoeff(&max_diff_axis);
|
||||||
|
scaling_factor = scale(max_diff_axis) * Vec3d::Ones();
|
||||||
|
}
|
||||||
|
|
||||||
|
TransformationType transformation_type(TransformationType::World_Relative_Joint);
|
||||||
|
if (selection.is_single_full_instance() && ! m_world_coordinates)
|
||||||
|
transformation_type.set_local();
|
||||||
|
selection.start_dragging();
|
||||||
|
selection.scale(scaling_factor * 0.01, transformation_type);
|
||||||
|
wxGetApp().plater()->canvas3D()->do_scale();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectManipulation::on_change(t_config_option_key opt_key, const boost::any& value)
|
||||||
{
|
{
|
||||||
// needed to hide the visual hints in 3D scene
|
// needed to hide the visual hints in 3D scene
|
||||||
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false);
|
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false);
|
||||||
@ -473,23 +407,19 @@ void ObjectManipulation::on_change(const t_config_option_key& opt_key, const boo
|
|||||||
if (!m_cache.is_valid())
|
if (!m_cache.is_valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<std::string> axes{ "_x", "_y", "_z" };
|
// Value of all three axes of the position / rotation / scale / size is extracted.
|
||||||
|
|
||||||
std::string param;
|
|
||||||
std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param));
|
|
||||||
|
|
||||||
size_t i = 0;
|
|
||||||
Vec3d new_value;
|
Vec3d new_value;
|
||||||
for (auto axis : axes)
|
opt_key.back() = 'x';
|
||||||
new_value(i++) = boost::any_cast<double>(m_og->get_value(param + axis));
|
for (int i = 0; i < 3; ++ i, ++ opt_key.back())
|
||||||
|
new_value(i) = boost::any_cast<double>(m_og->get_value(opt_key));
|
||||||
|
|
||||||
if (param == "position")
|
if (boost::starts_with(opt_key, "position_"))
|
||||||
change_position_value(new_value);
|
change_position_value(new_value);
|
||||||
else if (param == "rotation")
|
else if (boost::starts_with(opt_key, "rotation_"))
|
||||||
change_rotation_value(new_value);
|
change_rotation_value(new_value);
|
||||||
else if (param == "scale")
|
else if (boost::starts_with(opt_key, "scale_"))
|
||||||
change_scale_value(new_value);
|
change_scale_value(new_value);
|
||||||
else if (param == "size")
|
else if (boost::starts_with(opt_key, "size_"))
|
||||||
change_size_value(new_value);
|
change_size_value(new_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,21 +434,20 @@ void ObjectManipulation::on_fill_empty_value(const std::string& opt_key)
|
|||||||
if (!m_cache.is_valid())
|
if (!m_cache.is_valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string param;
|
const Vec3d *vec = nullptr;
|
||||||
std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param));
|
if (boost::starts_with(opt_key, "position_"))
|
||||||
|
vec = &m_cache.position;
|
||||||
|
else if (boost::starts_with(opt_key, "rotation_"))
|
||||||
|
vec = &m_cache.rotation;
|
||||||
|
else if (boost::starts_with(opt_key, "scale_"))
|
||||||
|
vec = &m_cache.scale;
|
||||||
|
else if (boost::starts_with(opt_key, "size_"))
|
||||||
|
vec = &m_cache.size;
|
||||||
|
else
|
||||||
|
assert(false);
|
||||||
|
|
||||||
double value = 0.0;
|
if (vec != nullptr)
|
||||||
auto opt_key_to_axis = [&opt_key]() { return opt_key.back() == 'x' ? 0 : opt_key.back() == 'y' ? 1 : 2; };
|
m_og->set_value(opt_key, double_to_string((*vec)(opt_key.back() - 'x')));
|
||||||
if (param == "position")
|
|
||||||
value = m_cache.position(opt_key_to_axis());
|
|
||||||
else if (param == "rotation")
|
|
||||||
value = m_cache.rotation(opt_key_to_axis());
|
|
||||||
else if (param == "scale")
|
|
||||||
value = m_cache.scale(opt_key_to_axis());
|
|
||||||
else if (param == "size")
|
|
||||||
value = m_cache.size(opt_key_to_axis());
|
|
||||||
|
|
||||||
m_og->set_value(opt_key, double_to_string(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} //namespace GUI
|
} //namespace GUI
|
||||||
|
@ -76,6 +76,8 @@ class ObjectManipulation : public OG_Settings
|
|||||||
Vec3d m_new_size;
|
Vec3d m_new_size;
|
||||||
bool m_new_enabled;
|
bool m_new_enabled;
|
||||||
bool m_uniform_scale {true};
|
bool m_uniform_scale {true};
|
||||||
|
// Does the object manipulation panel work in World or Local coordinates?
|
||||||
|
bool m_world_coordinates = true;
|
||||||
PrusaLockButton* m_lock_bnt{ nullptr };
|
PrusaLockButton* m_lock_bnt{ nullptr };
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
@ -98,6 +100,8 @@ public:
|
|||||||
|
|
||||||
void set_uniform_scaling(const bool uniform_scale) { m_uniform_scale = uniform_scale;}
|
void set_uniform_scaling(const bool uniform_scale) { m_uniform_scale = uniform_scale;}
|
||||||
bool get_uniform_scaling() const { return m_uniform_scale; }
|
bool get_uniform_scaling() const { return m_uniform_scale; }
|
||||||
|
// Does the object manipulation panel work in World or Local coordinates?
|
||||||
|
bool get_world_coordinates() const { return m_world_coordinates; }
|
||||||
|
|
||||||
void reset_cache() { m_cache.reset(); }
|
void reset_cache() { m_cache.reset(); }
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
@ -120,8 +124,9 @@ private:
|
|||||||
void change_rotation_value(const Vec3d& rotation);
|
void change_rotation_value(const Vec3d& rotation);
|
||||||
void change_scale_value(const Vec3d& scale);
|
void change_scale_value(const Vec3d& scale);
|
||||||
void change_size_value(const Vec3d& size);
|
void change_size_value(const Vec3d& size);
|
||||||
|
void do_scale(const Vec3d &scale) const;
|
||||||
|
|
||||||
void on_change(const t_config_option_key& opt_key, const boost::any& value);
|
void on_change(t_config_option_key opt_key, const boost::any& value);
|
||||||
void on_fill_empty_value(const std::string& opt_key);
|
void on_fill_empty_value(const std::string& opt_key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -629,7 +629,10 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
|
|||||||
case Scale:
|
case Scale:
|
||||||
{
|
{
|
||||||
// Apply new temporary scale factors
|
// Apply new temporary scale factors
|
||||||
selection.scale(get_scale(), evt.AltDown());
|
TransformationType transformation_type(TransformationType::World_Relative_Joint);
|
||||||
|
if (evt.AltDown())
|
||||||
|
transformation_type.set_independent();
|
||||||
|
selection.scale(get_scale(), transformation_type);
|
||||||
wxGetApp().obj_manipul()->update_settings_value(selection);
|
wxGetApp().obj_manipul()->update_settings_value(selection);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -104,8 +104,8 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||||||
main_shortcuts.push_back(Shortcut(ctrl+"S" ,L("Save project (3MF)")));
|
main_shortcuts.push_back(Shortcut(ctrl+"S" ,L("Save project (3MF)")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+alt+"L" ,L("Load Config from .ini/amf/3mf/gcode and merge")));
|
main_shortcuts.push_back(Shortcut(ctrl+alt+"L" ,L("Load Config from .ini/amf/3mf/gcode and merge")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"R" ,L("(Re)slice")));
|
main_shortcuts.push_back(Shortcut(ctrl+"R" ,L("(Re)slice")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"U" ,L("Quick slice")));
|
// main_shortcuts.push_back(Shortcut(ctrl+"U" ,L("Quick slice")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"Shift+U" ,L("Repeat last quick slice")));
|
// main_shortcuts.push_back(Shortcut(ctrl+"Shift+U" ,L("Repeat last quick slice")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"1" ,L("Select Plater Tab")));
|
main_shortcuts.push_back(Shortcut(ctrl+"1" ,L("Select Plater Tab")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+alt+"U" ,L("Quick slice and Save as")));
|
main_shortcuts.push_back(Shortcut(ctrl+alt+"U" ,L("Quick slice and Save as")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"2" ,L("Select Print Settings Tab")));
|
main_shortcuts.push_back(Shortcut(ctrl+"2" ,L("Select Print Settings Tab")));
|
||||||
|
@ -417,22 +417,21 @@ void ConfigOptionsGroup::back_to_config_value(const DynamicPrintConfig& config,
|
|||||||
|
|
||||||
void ConfigOptionsGroup::on_kill_focus(const std::string& opt_key)
|
void ConfigOptionsGroup::on_kill_focus(const std::string& opt_key)
|
||||||
{
|
{
|
||||||
if (m_fill_empty_value) {
|
if (m_fill_empty_value)
|
||||||
m_fill_empty_value(opt_key);
|
m_fill_empty_value(opt_key);
|
||||||
return;
|
else
|
||||||
}
|
|
||||||
reload_config();
|
reload_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigOptionsGroup::reload_config() {
|
void ConfigOptionsGroup::reload_config()
|
||||||
for (t_opt_map::iterator it = m_opt_map.begin(); it != m_opt_map.end(); ++it) {
|
{
|
||||||
auto opt_id = it->first;
|
for (auto &kvp : m_opt_map) {
|
||||||
std::string opt_key = m_opt_map.at(opt_id).first;
|
const std::string &opt_id = kvp.first;
|
||||||
int opt_index = m_opt_map.at(opt_id).second;
|
const std::string &opt_key = kvp.second.first;
|
||||||
auto option = m_options.at(opt_id).opt;
|
int opt_index = kvp.second.second;
|
||||||
set_value(opt_id, config_value(opt_key, opt_index, option.gui_flags.compare("serialized") == 0 ));
|
const ConfigOptionDef &option = m_options.at(opt_id).opt;
|
||||||
|
this->set_value(opt_key, config_value(opt_key, opt_index, option.gui_flags == "serialized"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigOptionsGroup::Hide()
|
void ConfigOptionsGroup::Hide()
|
||||||
|
@ -255,7 +255,7 @@ public:
|
|||||||
void back_to_initial_value(const std::string& opt_key) override;
|
void back_to_initial_value(const std::string& opt_key) override;
|
||||||
void back_to_sys_value(const std::string& opt_key) override;
|
void back_to_sys_value(const std::string& opt_key) override;
|
||||||
void back_to_config_value(const DynamicPrintConfig& config, const std::string& opt_key);
|
void back_to_config_value(const DynamicPrintConfig& config, const std::string& opt_key);
|
||||||
void on_kill_focus(const std::string& opt_key) override;// { reload_config(); }
|
void on_kill_focus(const std::string& opt_key) override;
|
||||||
void reload_config();
|
void reload_config();
|
||||||
// return value shows visibility : false => all options are hidden
|
// return value shows visibility : false => all options are hidden
|
||||||
void Hide();
|
void Hide();
|
||||||
|
@ -631,14 +631,17 @@ void Selection::flattening_rotate(const Vec3d& normal)
|
|||||||
m_bounding_box_dirty = true;
|
m_bounding_box_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Selection::scale(const Vec3d& scale, bool local)
|
void Selection::scale(const Vec3d& scale, TransformationType transformation_type)
|
||||||
{
|
{
|
||||||
if (!m_valid)
|
if (!m_valid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Only relative scaling values are allowed in the world coordinate system.
|
||||||
|
assert(! transformation_type.world() || transformation_type.relative());
|
||||||
|
|
||||||
for (unsigned int i : m_list)
|
for (unsigned int i : m_list)
|
||||||
{
|
{
|
||||||
if (is_single_full_instance())
|
if (is_single_full_instance() && ! transformation_type.world())
|
||||||
(*m_volumes)[i]->set_instance_scaling_factor(scale);
|
(*m_volumes)[i]->set_instance_scaling_factor(scale);
|
||||||
else if (is_single_volume() || is_single_modifier())
|
else if (is_single_volume() || is_single_modifier())
|
||||||
(*m_volumes)[i]->set_volume_scaling_factor(scale);
|
(*m_volumes)[i]->set_volume_scaling_factor(scale);
|
||||||
@ -650,7 +653,7 @@ void Selection::scale(const Vec3d& scale, bool local)
|
|||||||
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
|
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
|
||||||
// extracts scaling factors from the composed transformation
|
// extracts scaling factors from the composed transformation
|
||||||
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
||||||
if (!local)
|
if (transformation_type.joint())
|
||||||
(*m_volumes)[i]->set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
(*m_volumes)[i]->set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
||||||
|
|
||||||
(*m_volumes)[i]->set_instance_scaling_factor(new_scale);
|
(*m_volumes)[i]->set_instance_scaling_factor(new_scale);
|
||||||
@ -660,7 +663,7 @@ void Selection::scale(const Vec3d& scale, bool local)
|
|||||||
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3);
|
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3);
|
||||||
// extracts scaling factors from the composed transformation
|
// extracts scaling factors from the composed transformation
|
||||||
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
||||||
if (!local)
|
if (transformation_type.joint())
|
||||||
{
|
{
|
||||||
Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
|
Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
|
||||||
(*m_volumes)[i]->set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset);
|
(*m_volumes)[i]->set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset);
|
||||||
@ -959,7 +962,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) const
|
|||||||
|
|
||||||
const Vec3d& center = get_bounding_box().center();
|
const Vec3d& center = get_bounding_box().center();
|
||||||
|
|
||||||
if (is_single_full_instance())
|
if (is_single_full_instance() && ! wxGetApp().obj_manipul()->get_world_coordinates())
|
||||||
{
|
{
|
||||||
glsafe(::glTranslated(center(0), center(1), center(2)));
|
glsafe(::glTranslated(center(0), center(1), center(2)));
|
||||||
if (!boost::starts_with(sidebar_field, "position"))
|
if (!boost::starts_with(sidebar_field, "position"))
|
||||||
|
@ -269,7 +269,7 @@ public:
|
|||||||
void translate(const Vec3d& displacement, bool local = false);
|
void translate(const Vec3d& displacement, bool local = false);
|
||||||
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
||||||
void flattening_rotate(const Vec3d& normal);
|
void flattening_rotate(const Vec3d& normal);
|
||||||
void scale(const Vec3d& scale, bool local);
|
void scale(const Vec3d& scale, TransformationType transformation_type);
|
||||||
void mirror(Axis axis);
|
void mirror(Axis axis);
|
||||||
|
|
||||||
void translate(unsigned int object_idx, const Vec3d& displacement);
|
void translate(unsigned int object_idx, const Vec3d& displacement);
|
||||||
|
Loading…
Reference in New Issue
Block a user