Port Emboss & SVG gizmo from PrusaSlicer (#2819)

* Rework UI jobs to make them more understandable and flexible.

* Update Orca specific jobs

* Fix progress issue

* Fix dark mode and window radius

* Update cereal version from 1.2.2 to 1.3.0

(cherry picked from commit prusa3d/PrusaSlicer@057232a275)

* Initial port of Emboss gizmo

* Bump up CGAL version to 5.4

(cherry picked from commit prusa3d/PrusaSlicer@1bf9dee3e7)

* Fix text rotation

* Fix test dragging

* Add text gizmo to right click menu

* Initial port of SVG gizmo

* Fix text rotation

* Fix Linux build

* Fix "from surface"

* Fix -90 rotation

* Fix icon path

* Fix loading font with non-ascii name

* Fix storing non-utf8 font descriptor in 3mf file

* Fix filtering with non-utf8 characters

* Emboss: Use Orca style input dialog

* Fix build on macOS

* Fix tooltip color in light mode

* InputText: fixed incorrect padding when FrameBorder > 0. (ocornut/imgui#4794, ocornut/imgui#3781)
InputTextMultiline: fixed vertical tracking with large values of FramePadding.y. (ocornut/imgui#3781, ocornut/imgui#4794)

(cherry picked from commit ocornut/imgui@072caa4a90)
(cherry picked from commit ocornut/imgui@bdd2a94315)

* SVG: Use Orca style input dialog

* Fix job progress update

* Fix crash when select editing text in preview screen

* Use Orca checkbox style

* Fix issue that toolbar icons are kept regenerated

* Emboss: Fix text & icon alignment

* SVG: Fix text & icon alignment

* Emboss: fix toolbar icon mouse hover state

* Add a simple subtle outline effect by drawing back faces using wireframe mode

* Disable selection outlines

* Show outline in white if the model color is too dark

* Make the outline algorithm more reliable

* Enable cull face, which fix render on Linux

* Fix `disable_cullface`

* Post merge fix

* Optimize selection rendering

* Fix scale gizmo

* Emboss: Fix text rotation if base object is scaled

* Fix volume synchronize

* Fix emboss rotation

* Emboss: Fix advance toggle

* Fix text position after reopened the project

* Make font style preview darker

* Make font style preview selector height shorter

---------

Co-authored-by: tamasmeszaros <meszaros.q@gmail.com>
Co-authored-by: ocornut <omarcornut@gmail.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
Noisyfox
2023-12-09 22:46:18 +08:00
committed by GitHub
parent 7a8e1929ee
commit 933aa3050b
197 changed files with 27190 additions and 2454 deletions

View File

@@ -252,12 +252,17 @@ void GLGizmoBase::GizmoImguiEnd()
void GLGizmoBase::GizmoImguiSetNextWIndowPos(float &x, float y, int flag, float pivot_x, float pivot_y)
{
if (abs(last_input_window_width) > 0.01f) {
if (x + last_input_window_width > m_parent.get_canvas_size().get_width()) {
if (last_input_window_width > m_parent.get_canvas_size().get_width()) {
GizmoImguiSetNextWIndowPos(x, y, last_input_window_width, 0, flag, pivot_x, pivot_y);
}
void GLGizmoBase::GizmoImguiSetNextWIndowPos(float &x, float y, float w, float h, int flag, float pivot_x, float pivot_y)
{
if (abs(w) > 0.01f) {
if (x + w > m_parent.get_canvas_size().get_width()) {
if (w > m_parent.get_canvas_size().get_width()) {
x = 0;
} else {
x = m_parent.get_canvas_size().get_width() - last_input_window_width;
x = m_parent.get_canvas_size().get_width() - w;
}
}
}

View File

@@ -250,6 +250,7 @@ protected:
bool GizmoImguiBegin(const std::string& name, int flags);
void GizmoImguiEnd();
void GizmoImguiSetNextWIndowPos(float &x, float y, int flag, float pivot_x = 0.0f, float pivot_y = 0.0f);
void GizmoImguiSetNextWIndowPos(float &x, float y, float w, float h, int flag, float pivot_x = 0.0f, float pivot_y = 0.0f);
void register_grabbers_for_picking();
void unregister_grabbers_for_picking();

View File

@@ -1769,7 +1769,7 @@ BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(const Vec3d& plane_center,
// respect just to the solid parts for FFF and ignore pad and supports for SLA
if (!volume->is_modifier && !volume->is_sla_pad() && !volume->is_sla_support()) {
const auto instance_matrix = volume->get_instance_transformation().get_matrix(true);
const auto instance_matrix = volume->get_instance_transformation().get_matrix_no_offset();
auto volume_trafo = instance_matrix * volume->get_volume_transformation().get_matrix();
ret.merge(volume->transformed_convex_hull_bounding_box(cut_matrix * volume_trafo));
}
@@ -2284,13 +2284,13 @@ void GLGizmoCut3D::render_connectors_input_window(CutConnectors &connectors, flo
render_flip_plane_button(m_connectors_editing && connectors.empty());
m_imgui->text(m_labels_map["Type"]);
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(0.00f, 0.00f, 0.00f, 1.00f));
ImGuiWrapper::push_radio_style();
bool type_changed = render_connect_type_radio_button(CutConnectorType::Plug);
type_changed |= render_connect_type_radio_button(CutConnectorType::Dowel);
type_changed |= render_connect_type_radio_button(CutConnectorType::Snap);
if (type_changed)
apply_selected_connectors([this, &connectors] (size_t idx) { connectors[idx].attribs.type = CutConnectorType(m_connector_type); });
ImGui::PopStyleColor(1);
ImGuiWrapper::pop_radio_style();
m_imgui->disabled_begin(m_connector_type != CutConnectorType::Plug);
if (type_changed && m_connector_type == CutConnectorType::Dowel) {
@@ -2948,7 +2948,7 @@ void GLGizmoCut3D::show_tooltip_information(float x, float y)
ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
ImTextureID hover_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
caption_max += m_imgui->calc_text_size(": ").x + 35.f;
caption_max += m_imgui->calc_text_size(std::string_view{": "}).x + 35.f;
float font_size = ImGui::GetFontSize();
ImVec2 button_size = ImVec2(font_size * 1.8, font_size * 1.3);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,240 @@
///|/ Copyright (c) Prusa Research 2021 - 2023 Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Enrico Turri @enricoturri1966, Filip Sykala @Jony01
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#ifndef slic3r_GLGizmoEmboss_hpp_
#define slic3r_GLGizmoEmboss_hpp_
#include "GLGizmoBase.hpp"
#include "GLGizmoRotate.hpp"
#include "slic3r/GUI/IconManager.hpp"
#include "slic3r/GUI/SurfaceDrag.hpp"
#include "slic3r/GUI/I18N.hpp" // TODO: not needed
#include "slic3r/GUI/TextLines.hpp"
#include "slic3r/Utils/RaycastManager.hpp"
#include "slic3r/Utils/EmbossStyleManager.hpp"
#include <optional>
#include <memory>
#include <atomic>
#include "libslic3r/Emboss.hpp"
#include "libslic3r/Point.hpp"
#include "libslic3r/TextConfiguration.hpp"
#include <imgui/imgui.h>
#include <GL/glew.h>
class wxFont;
namespace Slic3r{
class AppConfig;
class GLVolume;
enum class ModelVolumeType : int;
}
namespace Slic3r::GUI {
class GLGizmoEmboss : public GLGizmoBase
{
public:
explicit GLGizmoEmboss(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id);
/// <summary>
/// Create new embossed text volume by type on position of mouse
/// </summary>
/// <param name="volume_type">Object part / Negative volume / Modifier</param>
/// <param name="mouse_pos">Define position of new volume</param>
bool create_volume(ModelVolumeType volume_type, const Vec2d &mouse_pos);
/// <summary>
/// Create new text without given position
/// </summary>
/// <param name="volume_type">Object part / Negative volume / Modifier</param>
bool create_volume(ModelVolumeType volume_type);
/// <summary>
/// Handle pressing of shortcut
/// </summary>
void on_shortcut_key();
/// <summary>
/// Mirroring from object manipulation panel
/// !! Emboss gizmo must be active
/// </summary>
/// <param name="axis">Axis for mirroring must be one of {0,1,2}</param>
/// <returns>True on success start job otherwise False</returns>
bool do_mirror(size_t axis);
/// <summary>
/// Call on change inside of object conatining projected volume
/// </summary>
/// <param name="job_cancel">Way to stop re_emboss job</param>
/// <returns>True on success otherwise False</returns>
static bool re_emboss(const ModelVolume &text, std::shared_ptr<std::atomic<bool>> job_cancel = nullptr);
protected:
bool on_init() override;
std::string on_get_name() const override;
void on_render() override;
void on_register_raycasters_for_picking() override;
void on_unregister_raycasters_for_picking() override;
void on_render_input_window(float x, float y, float bottom_limit) override;
void on_set_state() override;
void data_changed(bool is_serializing) override; // selection changed
void on_set_hover_id() override{ m_rotate_gizmo.set_hover_id(m_hover_id); }
void on_enable_grabber(unsigned int id) override { m_rotate_gizmo.enable_grabber(); }
void on_disable_grabber(unsigned int id) override { m_rotate_gizmo.disable_grabber(); }
void on_start_dragging() override;
void on_stop_dragging() override;
void on_dragging(const UpdateData &data) override;
void push_button_style(bool pressed);
void pop_button_style();
/// <summary>
/// Rotate by text on dragging rotate grabers
/// </summary>
/// <param name="mouse_event">Information about mouse</param>
/// <returns>Propagete normaly return false.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
bool wants_enter_leave_snapshots() const override;
std::string get_gizmo_entering_text() const override;
std::string get_gizmo_leaving_text() const override;
std::string get_action_snapshot_name() const override;
private:
void volume_transformation_changing();
void volume_transformation_changed();
static EmbossStyles create_default_styles();
// localized default text
bool init_create(ModelVolumeType volume_type);
void set_volume_by_selection();
void reset_volume();
// create volume from text - main functionality
bool process();
void close();
void draw_window();
void draw_text_input();
void draw_model_type();
void draw_style_list();
void draw_delete_style_button();
void draw_style_rename_popup();
void draw_style_rename_button();
void draw_style_save_button(bool is_modified);
void draw_style_save_as_popup();
void draw_style_add_button();
void init_font_name_texture();
void draw_font_list_line();
void draw_font_list();
void draw_height(bool use_inch);
void draw_depth(bool use_inch);
// call after set m_style_manager.get_style().prop.size_in_mm
bool set_height();
bool draw_italic_button();
bool draw_bold_button();
void draw_advanced();
bool select_facename(const wxString& facename);
template<typename T> bool rev_input_mm(const std::string &name, T &value, const T *default_value,
const std::string &undo_tooltip, T step, T step_fast, const char *format, bool use_inch, const std::optional<float>& scale) const;
/// <summary>
/// Reversible input float with option to restor default value
/// TODO: make more general, static and move to ImGuiWrapper
/// </summary>
/// <returns>True when value changed otherwise FALSE.</returns>
template<typename T> bool rev_input(const std::string &name, T &value, const T *default_value,
const std::string &undo_tooltip, T step, T step_fast, const char *format, ImGuiInputTextFlags flags = 0) const;
bool rev_checkbox(const std::string &name, bool &value, const bool* default_value, const std::string &undo_tooltip) const;
bool rev_slider(const std::string &name, std::optional<int>& value, const std::optional<int> *default_value,
const std::string &undo_tooltip, int v_min, int v_max, const std::string &format, const wxString &tooltip) const;
bool rev_slider(const std::string &name, std::optional<float>& value, const std::optional<float> *default_value,
const std::string &undo_tooltip, float v_min, float v_max, const std::string &format, const wxString &tooltip) const;
bool rev_slider(const std::string &name, float &value, const float *default_value,
const std::string &undo_tooltip, float v_min, float v_max, const std::string &format, const wxString &tooltip) const;
template<typename T, typename Draw> bool revertible(const std::string &name, T &value, const T *default_value,
const std::string &undo_tooltip, float undo_offset, Draw draw) const;
// process mouse event
bool on_mouse_for_rotation(const wxMouseEvent &mouse_event);
bool on_mouse_for_translate(const wxMouseEvent &mouse_event);
void on_mouse_change_selection(const wxMouseEvent &mouse_event);
// When open text loaded from .3mf it could be written with unknown font
bool m_is_unknown_font = false;
void create_notification_not_valid_font(const TextConfiguration& tc);
void create_notification_not_valid_font(const std::string& text);
void remove_notification_not_valid_font();
struct GuiCfg;
std::unique_ptr<const GuiCfg> m_gui_cfg;
// Is open tree with advanced options
bool m_is_advanced_edit_style = false;
// Keep information about stored styles and loaded actual style to compare with
Emboss::StyleManager m_style_manager;
// pImpl to hide implementation of FaceNames to .cpp file
struct Facenames; // forward declaration
std::unique_ptr<Facenames> m_face_names;
// Text to emboss
std::string m_text; // Sequence of Unicode UTF8 symbols
// When true keep up vector otherwise relative rotation
bool m_keep_up = true;
// current selected volume
// NOTE: Be carefull could be uninitialized (removed from Model)
ModelVolume *m_volume = nullptr;
// When work with undo redo stack there could be situation that
// m_volume point to unexisting volume so One need also objectID
ObjectID m_volume_id;
// True when m_text contain character unknown by selected font
bool m_text_contain_unknown_glyph = false;
// cancel for previous update of volume to cancel finalize part
std::shared_ptr<std::atomic<bool>> m_job_cancel = nullptr;
// Keep information about curvature of text line around surface
TextLinesModel m_text_lines;
void reinit_text_lines(unsigned count_lines=0);
// Rotation gizmo
GLGizmoRotate m_rotate_gizmo;
// Value is set only when dragging rotation to calculate actual angle
std::optional<float> m_rotate_start_angle;
// Keep data about dragging only during drag&drop
std::optional<SurfaceDrag> m_surface_drag;
// Keep old scene triangle data in AABB trees,
// all the time it need actualize before use.
RaycastManager m_raycast_manager;
// For text on scaled objects
std::optional<float> m_scale_height;
std::optional<float> m_scale_depth;
void calculate_scale();
// drawing icons
IconManager m_icon_manager;
IconManager::VIcons m_icons;
void init_icons();
// only temporary solution
static const std::string M_ICON_FILENAME;
};
} // namespace Slic3r::GUI
#endif // slic3r_GLGizmoEmboss_hpp_

View File

@@ -513,7 +513,7 @@ void GLGizmoFdmSupports::show_tooltip_information(float caption_max, float x, fl
ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
ImTextureID hover_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
caption_max += m_imgui->calc_text_size(": ").x + 15.f;
caption_max += m_imgui->calc_text_size(std::string_view{": "}).x + 15.f;
float font_size = ImGui::GetFontSize();
ImVec2 button_size = ImVec2(font_size * 1.8, font_size * 1.3);
@@ -584,7 +584,7 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block)
++mesh_id;
const Transform3d trafo_matrix = mi->get_matrix(true) * mv->get_matrix(true);
const Transform3d trafo_matrix = mi->get_matrix_no_offset() * mv->get_matrix_no_offset();
Vec3f down = (trafo_matrix.inverse() * (-Vec3d::UnitZ())).cast<float>().normalized();
Vec3f limit = (trafo_matrix.inverse() * Vec3d(std::sin(threshold), 0, -std::cos(threshold))).cast<float>().normalized();

View File

@@ -165,7 +165,7 @@ void GLGizmoFlatten::update_planes()
ch = ch.convex_hull_3d();
m_planes.clear();
on_unregister_raycasters_for_picking();
const Transform3d& inst_matrix = mo->instances.front()->get_matrix(true);
const Transform3d &inst_matrix = mo->instances.front()->get_matrix_no_offset();
// Following constants are used for discarding too small polygons.
const float minimal_area = 5.f; // in square mm (world coordinates)

View File

@@ -2042,7 +2042,7 @@ void GLGizmoMeasure::show_tooltip_information(float caption_max, float x, float
ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
ImTextureID hover_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
caption_max += m_imgui->calc_text_size(": ").x + 35.f;
caption_max += m_imgui->calc_text_size(std::string_view{": "}).x + 35.f;
float font_size = ImGui::GetFontSize();
ImVec2 button_size = ImVec2(font_size * 1.8, font_size * 1.3);

View File

@@ -451,7 +451,7 @@ void GLGizmoMeshBoolean::generate_new_volume(bool delete_input, const TriangleMe
new_volume->set_material_id(old_volume->material_id());
new_volume->set_offset(old_volume->get_transformation().get_offset());
//Vec3d translate_z = { 0,0, (new_volume->source.mesh_offset - old_volume->source.mesh_offset).z() };
//new_volume->translate(new_volume->get_transformation().get_matrix(true) * translate_z);
//new_volume->translate(new_volume->get_transformation().get_matrix_no_offset() * translate_z);
//new_volume->supported_facets.assign(old_volume->supported_facets);
//new_volume->seam_facets.assign(old_volume->seam_facets);
//new_volume->mmu_segmentation_facets.assign(old_volume->mmu_segmentation_facets);

View File

@@ -341,7 +341,7 @@ void GLGizmoMmuSegmentation::show_tooltip_information(float caption_max, float x
ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
ImTextureID hover_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
caption_max += m_imgui->calc_text_size(": ").x + 15.f;
caption_max += m_imgui->calc_text_size(std::string_view{": "}).x + 15.f;
float font_size = ImGui::GetFontSize();
ImVec2 button_size = ImVec2(font_size * 1.8, font_size * 1.3);
@@ -408,7 +408,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
const float filter_btn_width = m_imgui->calc_text_size(m_desc.at("perform")).x + m_imgui->scaled(1.f);
const float buttons_width = remove_btn_width + filter_btn_width + m_imgui->scaled(1.f);
const float minimal_slider_width = m_imgui->scaled(4.f);
const float color_button_width = m_imgui->calc_text_size("").x + m_imgui->scaled(1.75f);
const float color_button_width = m_imgui->calc_text_size(std::string_view{""}).x + m_imgui->scaled(1.75f);
float caption_max = 0.f;
float total_text_max = 0.f;

View File

@@ -107,7 +107,15 @@ void GLGizmoMove3D::on_dragging(const UpdateData& data)
m_displacement.z() = calc_projection(data);
Selection &selection = m_parent.get_selection();
selection.translate(m_displacement);
TransformationType trafo_type;
trafo_type.set_relative();
switch (wxGetApp().obj_manipul()->get_coordinates_type())
{
case ECoordinatesType::Instance: { trafo_type.set_instance(); break; }
case ECoordinatesType::Local: { trafo_type.set_local(); break; }
default: { break; }
}
selection.translate(m_displacement, trafo_type);
}
void GLGizmoMove3D::on_render()

View File

@@ -245,7 +245,7 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
if (shader == nullptr)
return;
const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_matrix(true, true, false, true).inverse();
const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_matrix_no_scaling_factor().inverse();
// BBS
ColorRGBA render_color = this->get_cursor_hover_color();
@@ -536,8 +536,8 @@ std::vector<GLGizmoPainterBase::ProjectedHeightRange> GLGizmoPainterBase::get_pr
mi->get_assemble_transformation().get_matrix() :
mi->get_transformation().get_matrix();
const Transform3d instance_trafo_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix(true) :
mi->get_transformation().get_matrix(true);
mi->get_assemble_transformation().get_matrix_no_offset() :
mi->get_transformation().get_matrix_no_offset();
for (int mesh_idx = 0; mesh_idx < part_volumes.size(); mesh_idx++) {
if (mesh_idx == m_rr.mesh_id)
@@ -605,8 +605,8 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
const ModelObject *mo = m_c->selection_info()->model_object();
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
const Transform3d trafo_matrix_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix(true) * mo->volumes[m_rr.mesh_id]->get_matrix(true) :
mi->get_transformation().get_matrix(true) * mo->volumes[m_rr.mesh_id]->get_matrix(true);
mi->get_assemble_transformation().get_matrix_no_offset() * mo->volumes[m_rr.mesh_id]->get_matrix_no_offset() :
mi->get_transformation().get_matrix_no_offset() * mo->volumes[m_rr.mesh_id]->get_matrix_no_offset();
const Transform3d trafo_matrix = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix() :
mi->get_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix();
@@ -675,8 +675,8 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
mi->get_assemble_transformation().get_matrix() :
mi->get_transformation().get_matrix();
Transform3d instance_trafo_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix(true) :
mi->get_transformation().get_matrix(true);
mi->get_assemble_transformation().get_matrix_no_offset() :
mi->get_transformation().get_matrix_no_offset();
std::vector<const ModelVolume*> part_volumes;
// Precalculate transformations of individual meshes.
@@ -692,7 +692,7 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
else {
trafo_matrices.emplace_back(instance_trafo* mv->get_matrix());
}
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix(true));
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix_no_offset());
part_volumes.push_back(mv);
}
@@ -824,8 +824,8 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
mi->get_assemble_transformation().get_matrix() :
mi->get_transformation().get_matrix();
const Transform3d instance_trafo_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix(true) :
mi->get_transformation().get_matrix(true);
mi->get_assemble_transformation().get_matrix_no_offset() :
mi->get_transformation().get_matrix_no_offset();
// Precalculate transformations of individual meshes.
std::vector<Transform3d> trafo_matrices;
@@ -840,7 +840,7 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
else {
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
}
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix(true));
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix_no_offset());
}
// Now "click" into all the prepared points and spill paint around them.

View File

@@ -6,14 +6,14 @@
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/ImGuiWrapper.hpp"
#include <GL/glew.h>
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/Jobs/RotoptimizeJob.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "slic3r/GUI/Jobs/RotoptimizeJob.hpp"
#include <GL/glew.h>
namespace Slic3r {
namespace GUI {
@@ -28,10 +28,16 @@ const float GLGizmoRotate::ScaleLongTooth = 0.1f; // in percent of radius
const unsigned int GLGizmoRotate::SnapRegionsCount = 8;
const float GLGizmoRotate::GrabberOffset = 0.15f; // in percent of radius
GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis)
: GLGizmoBase(parent, "", -1)
, m_axis(axis)
, m_angle(0.0)
, m_center(0.0, 0.0, 0.0)
, m_radius(0.0f)
, m_snap_coarse_in_radius(0.0f)
, m_snap_coarse_out_radius(0.0f)
, m_snap_fine_in_radius(0.0f)
, m_snap_fine_out_radius(0.0f)
, m_drag_color(DEFAULT_DRAG_COLOR)
, m_highlight_color(DEFAULT_HIGHLIGHT_COLOR)
{
@@ -94,19 +100,12 @@ bool GLGizmoRotate::on_init()
void GLGizmoRotate::on_start_dragging()
{
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
m_center = m_custom_center == Vec3d::Zero() ? box.center() : m_custom_center;
m_radius = Offset + box.radius();
m_snap_coarse_in_radius = m_radius / 3.0f;
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
m_snap_fine_in_radius = m_radius;
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
init_data_from_selection(m_parent.get_selection());
}
void GLGizmoRotate::on_dragging(const UpdateData &data)
{
const Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, m_parent.get_selection()));
const Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray));
const Vec2d orig_dir = Vec2d::UnitX();
const Vec2d new_dir = mouse_pos.normalized();
@@ -141,16 +140,8 @@ void GLGizmoRotate::on_render()
return;
const Selection& selection = m_parent.get_selection();
const BoundingBoxf3& box = selection.get_bounding_box();
if (m_hover_id != 0 && !m_grabbers.front().dragging) {
m_center = m_custom_center == Vec3d::Zero() ? box.center() : m_custom_center;
m_radius = Offset + box.radius();
m_snap_coarse_in_radius = m_radius / 3.0f;
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
m_snap_fine_in_radius = m_radius;
m_snap_fine_out_radius = m_radius * (1.0f + ScaleLongTooth);
}
if (m_hover_id != 0 && !m_grabbers.front().dragging)
init_data_from_selection(selection);
const double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset);
m_grabbers.front().center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0);
@@ -168,15 +159,14 @@ void GLGizmoRotate::on_render()
shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d view_model_matrix = camera.get_view_matrix() * m_grabbers.front().matrix;
const Transform3d view_model_matrix = camera.get_view_matrix() * m_grabbers.front().matrix;
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
const bool radius_changed = std::abs(m_old_radius - m_radius) > EPSILON;
m_old_radius = m_radius;
ColorRGBA color((m_hover_id != -1) ? m_drag_color : m_highlight_color);
const ColorRGBA color = (m_hover_id != -1) ? m_drag_color : m_highlight_color;
render_circle(color, radius_changed);
if (m_hover_id != -1) {
const bool hover_radius_changed = std::abs(m_old_hover_radius - m_radius) > EPSILON;
@@ -192,7 +182,23 @@ void GLGizmoRotate::on_render()
shader->stop_using();
}
render_grabber(box);
render_grabber(m_bounding_box);
}
void GLGizmoRotate::init_data_from_selection(const Selection& selection)
{
const auto [box, box_trafo] = m_force_local_coordinate ?
selection.get_bounding_box_in_reference_system(ECoordinatesType::Local) : selection.get_bounding_box_in_current_reference_system();
m_bounding_box = box;
const std::pair<Vec3d, double> sphere = selection.get_bounding_sphere();
m_center = sphere.first;
m_radius = Offset + sphere.second;
m_orient_matrix = box_trafo;
m_orient_matrix.translation() = m_center;
m_snap_coarse_in_radius = m_radius / 3.0f;
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
m_snap_fine_in_radius = m_radius;
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
}
//BBS: add input window for move
@@ -422,12 +428,12 @@ Transform3d GLGizmoRotate::local_transform(const Selection& selection) const
{
case X:
{
ret = Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY()) * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitZ());
ret = Geometry::rotation_transform(0.5 * PI * Vec3d::UnitY()) * Geometry::rotation_transform(-0.5 * PI * Vec3d::UnitZ());
break;
}
case Y:
{
ret = Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitZ()) * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitY());
ret = Geometry::rotation_transform(-0.5 * PI * Vec3d::UnitZ()) * Geometry::rotation_transform(-0.5 * PI * Vec3d::UnitY());
break;
}
default:
@@ -438,13 +444,10 @@ Transform3d GLGizmoRotate::local_transform(const Selection& selection) const
}
}
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
ret = selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true) * ret;
return Geometry::assemble_transform(m_center) * ret;
return m_orient_matrix * ret;
}
Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const
Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray) const
{
const double half_pi = 0.5 * double(PI);
@@ -472,8 +475,7 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons
}
}
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
m = m * selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true).inverse();
m = m * Geometry::Transformation(m_orient_matrix).get_matrix_no_offset().inverse();
m.translate(-m_center);
@@ -496,19 +498,32 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons
//BBS: GUI refactor: add obj manipulation
GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation)
: GLGizmoBase(parent, icon_filename, sprite_id)
, m_gizmos({ GLGizmoRotate(parent, GLGizmoRotate::X), GLGizmoRotate(parent, GLGizmoRotate::Y), GLGizmoRotate(parent, GLGizmoRotate::Z) })
//BBS: GUI refactor: add obj manipulation
, m_gizmos({
GLGizmoRotate(parent, GLGizmoRotate::X),
GLGizmoRotate(parent, GLGizmoRotate::Y),
GLGizmoRotate(parent, GLGizmoRotate::Z) })
//BBS: GUI refactor: add obj manipulation
, m_object_manipulation(obj_manipulation)
{
load_rotoptimize_state();
}
bool GLGizmoRotate3D::on_mouse(const wxMouseEvent &mouse_event) {
bool GLGizmoRotate3D::on_mouse(const wxMouseEvent &mouse_event)
{
if (mouse_event.Dragging() && m_dragging) {
// Apply new temporary rotations
TransformationType transformation_type(
TransformationType::World_Relative_Joint);
TransformationType transformation_type;
if (m_parent.get_selection().is_wipe_tower())
transformation_type = TransformationType::World_Relative_Joint;
else {
switch (wxGetApp().obj_manipul()->get_coordinates_type())
{
default:
case ECoordinatesType::World: { transformation_type = TransformationType::World_Relative_Joint; break; }
case ECoordinatesType::Instance: { transformation_type = TransformationType::Instance_Relative_Joint; break; }
case ECoordinatesType::Local: { transformation_type = TransformationType::Local_Relative_Joint; break; }
}
}
if (mouse_event.AltDown())
transformation_type.set_independent();
m_parent.get_selection().rotate(get_rotation(), transformation_type);
@@ -669,11 +684,12 @@ GLGizmoRotate3D::RotoptimzeWindow::RotoptimzeWindow(ImGuiWrapper * imgui,
ImVec2 button_sz = {btn_txt_sz.x + padding.x, btn_txt_sz.y + padding.y};
ImGui::SetCursorPosX(padding.x + sz.x - button_sz.x);
if (wxGetApp().plater()->is_any_job_running())
if (!wxGetApp().plater()->get_ui_job_worker().is_idle())
imgui->disabled_begin(true);
if ( imgui->button(btn_txt) ) {
wxGetApp().plater()->optimize_rotation();
replace_job(wxGetApp().plater()->get_ui_job_worker(),
std::make_unique<RotoptimizeJob>());
}
imgui->disabled_end();

View File

@@ -6,14 +6,13 @@
#define slic3r_GLGizmoRotate_hpp_
#include "GLGizmoBase.hpp"
#include "../Jobs/RotoptimizeJob.hpp"
//BBS: add size adjust related
#include "GizmoObjectManipulation.hpp"
namespace Slic3r {
namespace GUI {
class Selection;
class GLGizmoRotate : public GLGizmoBase
{
static const float Offset;
@@ -36,16 +35,14 @@ public:
private:
Axis m_axis;
double m_angle{ 0.0 };
Vec3d m_custom_center{Vec3d::Zero()};
Vec3d m_center{ Vec3d::Zero() };
float m_radius{ 0.0f };
float m_snap_coarse_in_radius{ 0.0f };
float m_snap_coarse_out_radius{ 0.0f };
float m_snap_fine_in_radius{ 0.0f };
float m_snap_fine_out_radius{ 0.0f };
ColorRGBA m_drag_color;
ColorRGBA m_highlight_color;
BoundingBoxf3 m_bounding_box;
Transform3d m_orient_matrix{ Transform3d::Identity() };
GLModel m_circle;
GLModel m_scale;
@@ -62,6 +59,12 @@ private:
float m_old_hover_radius{ 0.0f };
float m_old_angle{ 0.0f };
// emboss need to draw rotation gizmo in local coordinate systems
bool m_force_local_coordinate{ false };
ColorRGBA m_drag_color;
ColorRGBA m_highlight_color;
public:
GLGizmoRotate(GLCanvas3D& parent, Axis axis);
virtual ~GLGizmoRotate() = default;
@@ -71,7 +74,8 @@ public:
std::string get_tooltip() const override;
void set_center(const Vec3d &point) { m_custom_center = point; }
void set_group_id(int group_id) { m_group_id = group_id; }
void set_force_local_coordinate(bool use) { m_force_local_coordinate = use; }
void start_dragging();
void stop_dragging();
@@ -109,7 +113,9 @@ private:
Transform3d local_transform(const Selection& selection) const;
// 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 Selection& selection) const;
Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray) const;
void init_data_from_selection(const Selection& selection);
};
class GLGizmoRotate3D : public GLGizmoBase
@@ -138,13 +144,6 @@ public:
return tooltip;
}
void set_center(const Vec3d &point)
{
m_gizmos[X].set_center(point);
m_gizmos[Y].set_center(point);
m_gizmos[Z].set_center(point);
}
/// <summary>
/// Postpone to Rotation
/// </summary>
@@ -164,7 +163,14 @@ protected:
for (int i = 0; i < 3; ++i)
m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
}
void on_enable_grabber(unsigned int id) override {
if (id < 3)
m_gizmos[id].enable_grabber();
}
void on_disable_grabber(unsigned int id) override {
if (id < 3)
m_gizmos[id].disable_grabber();
}
bool on_is_activable() const override;
void on_start_dragging() override;
void on_stop_dragging() override;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,200 @@
#ifndef slic3r_GLGizmoSVG_hpp_
#define slic3r_GLGizmoSVG_hpp_
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code,
// which overrides our localization "L" macro.
#include "GLGizmoBase.hpp"
#include "GLGizmoRotate.hpp"
#include "slic3r/GUI/SurfaceDrag.hpp"
#include "slic3r/GUI/GLTexture.hpp"
#include "slic3r/Utils/RaycastManager.hpp"
#include "slic3r/GUI/IconManager.hpp"
#include <optional>
#include <memory>
#include <atomic>
#include "libslic3r/Emboss.hpp"
#include "libslic3r/Point.hpp"
#include "libslic3r/Model.hpp"
#include <imgui/imgui.h>
#include <GL/glew.h>
namespace Slic3r{
class ModelVolume;
enum class ModelVolumeType : int;
}
namespace Slic3r::GUI {
struct Texture{
unsigned id{0};
unsigned width{0};
unsigned height{0};
};
class GLGizmoSVG : public GLGizmoBase
{
public:
explicit GLGizmoSVG(GLCanvas3D &parent);
/// <summary>
/// Create new embossed text volume by type on position of mouse
/// </summary>
/// <param name="volume_type">Object part / Negative volume / Modifier</param>
/// <param name="mouse_pos">Define position of new volume</param>
/// <returns>True on succesfull start creation otherwise False</returns>
bool create_volume(ModelVolumeType volume_type, const Vec2d &mouse_pos); // first open file dialog
/// <summary>
/// Create new text without given position
/// </summary>
/// <param name="volume_type">Object part / Negative volume / Modifier</param>
/// <returns>True on succesfull start creation otherwise False</returns>
bool create_volume(ModelVolumeType volume_type); // first open file dialog
/// <summary>
/// Create volume from already selected svg file
/// </summary>
/// <param name="svg_file">File path</param>
/// <param name="mouse_pos">Position on screen where to create volume</param>
/// <param name="volume_type">Object part / Negative volume / Modifier</param>
/// <returns>True on succesfull start creation otherwise False</returns>
bool create_volume(std::string_view svg_file, const Vec2d &mouse_pos, ModelVolumeType volume_type = ModelVolumeType::MODEL_PART);
bool create_volume(std::string_view svg_file, ModelVolumeType volume_type = ModelVolumeType::MODEL_PART);
/// <summary>
/// Check whether volume is object containing only emboss volume
/// </summary>
/// <param name="volume">Pointer to volume</param>
/// <returns>True when object otherwise False</returns>
static bool is_svg_object(const ModelVolume &volume);
/// <summary>
/// Check whether volume has emboss data
/// </summary>
/// <param name="volume">Pointer to volume</param>
/// <returns>True when constain emboss data otherwise False</returns>
static bool is_svg(const ModelVolume &volume);
protected:
bool on_init() override;
std::string on_get_name() const override;
void on_render() override;
void on_register_raycasters_for_picking() override;
void on_unregister_raycasters_for_picking() override;
void on_render_input_window(float x, float y, float bottom_limit) override;
bool on_is_activable() const override { return true; }
bool on_is_selectable() const override { return false; }
void on_set_state() override;
void data_changed(bool is_serializing) override; // selection changed
void on_set_hover_id() override{ m_rotate_gizmo.set_hover_id(m_hover_id); }
void on_enable_grabber(unsigned int id) override { m_rotate_gizmo.enable_grabber(); }
void on_disable_grabber(unsigned int id) override { m_rotate_gizmo.disable_grabber(); }
void on_start_dragging() override;
void on_stop_dragging() override;
void on_dragging(const UpdateData &data) override;
/// <summary>
/// Rotate by text on dragging rotate grabers
/// </summary>
/// <param name="mouse_event">Information about mouse</param>
/// <returns>Propagete normaly return false.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
bool wants_enter_leave_snapshots() const override;
std::string get_gizmo_entering_text() const override;
std::string get_gizmo_leaving_text() const override;
std::string get_action_snapshot_name() const override;
private:
void set_volume_by_selection();
void reset_volume();
// create volume from text - main functionality
bool process();
void close();
void draw_window();
void draw_preview();
void draw_filename();
void draw_depth();
void draw_size();
void draw_use_surface();
void draw_distance();
void draw_rotation();
void draw_mirroring();
void draw_face_the_camera();
void draw_model_type();
// process mouse event
bool on_mouse_for_rotation(const wxMouseEvent &mouse_event);
bool on_mouse_for_translate(const wxMouseEvent &mouse_event);
void volume_transformation_changed();
struct GuiCfg;
std::unique_ptr<const GuiCfg> m_gui_cfg;
// actual selected only one volume - with emboss data
ModelVolume *m_volume = nullptr;
// Is used to edit eboss and send changes to job
// Inside volume is current state of shape WRT Volume
EmbossShape m_volume_shape; // copy from m_volume for edit
// same index as volumes in
std::vector<std::string> m_shape_warnings;
// When work with undo redo stack there could be situation that
// m_volume point to unexisting volume so One need also objectID
ObjectID m_volume_id;
// cancel for previous update of volume to cancel finalize part
std::shared_ptr<std::atomic<bool>> m_job_cancel = nullptr;
// Rotation gizmo
GLGizmoRotate m_rotate_gizmo;
std::optional<float> m_angle;
std::optional<float> m_distance;
// Value is set only when dragging rotation to calculate actual angle
std::optional<float> m_rotate_start_angle;
// TODO: it should be accessible by other gizmo too.
// May be move to plater?
RaycastManager m_raycast_manager;
// When true keep up vector otherwise relative rotation
bool m_keep_up = true;
// Keep size aspect ratio when True.
bool m_keep_ratio = true;
// Keep data about dragging only during drag&drop
std::optional<SurfaceDrag> m_surface_drag;
// For volume on scaled objects
std::optional<float> m_scale_width;
std::optional<float> m_scale_height;
std::optional<float> m_scale_depth;
void calculate_scale();
float get_scale_for_tolerance();
// keep SVG data rendered on GPU
Texture m_texture;
// bounding box of shape
// Note: Scaled mm to int value by m_volume_shape.scale
BoundingBox m_shape_bb;
std::string m_filename_preview;
IconManager m_icon_manager;
IconManager::VIcons m_icons;
// only temporary solution
static const std::string M_ICON_FILENAME;
};
} // namespace Slic3r::GUI
#endif // slic3r_GLGizmoSVG_hpp_

View File

@@ -48,7 +48,7 @@ std::string GLGizmoScale3D::get_tooltip() const
const Selection& selection = m_parent.get_selection();
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_volume_or_modifier();
Vec3f scale = 100.0f * Vec3f::Ones();
if (single_instance)
@@ -85,13 +85,21 @@ bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event)
if (mouse_event.Dragging()) {
if (m_dragging) {
// Apply new temporary scale factors
TransformationType transformation_type(TransformationType::Local_Absolute_Joint);
Selection& selection = m_parent.get_selection();
TransformationType transformation_type;
if (selection.is_single_full_instance()) {
transformation_type.set_instance();
} else if (selection.is_single_volume_or_modifier()) {
transformation_type.set_local();
}
transformation_type.set_relative();
if (mouse_event.AltDown())
transformation_type.set_independent();
Selection& selection = m_parent.get_selection();
selection.scale(m_scale, transformation_type);
if (mouse_event.CmdDown()) selection.translate(m_offset, true);
if (mouse_event.CmdDown()) selection.translate(m_offset, transformation_type);
}
}
return use_grabbers(mouse_event);
@@ -100,24 +108,11 @@ bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event)
void GLGizmoScale3D::data_changed(bool is_serializing) {
const Selection &selection = m_parent.get_selection();
bool enable_scale_xyz = selection.is_single_full_instance() ||
selection.is_single_volume() ||
selection.is_single_modifier();
selection.is_single_volume_or_modifier();
for (unsigned int i = 0; i < 6; ++i)
m_grabbers[i].enabled = enable_scale_xyz;
if (enable_scale_xyz) {
// all volumes in the selection belongs to the same instance, any of
// them contains the needed data, so we take the first
const GLVolume *volume = selection.get_first_volume();
if (selection.is_single_full_instance()) {
set_scale(volume->get_instance_scaling_factor());
} else if (selection.is_single_volume() ||
selection.is_single_modifier()) {
set_scale(volume->get_volume_scaling_factor());
}
} else {
set_scale(Vec3d::Ones());
}
set_scale(Vec3d::Ones());
}
bool GLGizmoScale3D::on_init()
@@ -193,7 +188,7 @@ void GLGizmoScale3D::on_render()
const Selection& selection = m_parent.get_selection();
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_volume_or_modifier();
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST));

View File

@@ -151,7 +151,7 @@ void GLGizmoSeam::show_tooltip_information(float caption_max, float x, float y)
ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
ImTextureID hover_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
caption_max += m_imgui->calc_text_size(": ").x + 35.f;
caption_max += m_imgui->calc_text_size(std::string_view{": "}).x + 35.f;
float font_size = ImGui::GetFontSize();
ImVec2 button_size = ImVec2(font_size * 1.8, font_size * 1.3);

View File

@@ -582,7 +582,7 @@ void GLGizmoSimplify::on_set_state()
void GLGizmoSimplify::create_gui_cfg() {
if (m_gui_cfg.has_value()) return;
int space_size = m_imgui->calc_text_size(":MM").x;
int space_size = m_imgui->calc_text_size(std::string_view{":MM"}).x;
GuiCfg cfg;
cfg.top_left_width = std::max(m_imgui->calc_text_size(tr_mesh_name).x,
m_imgui->calc_text_size(tr_triangles).x)

View File

@@ -26,8 +26,9 @@
#include "slic3r/GUI/Gizmos/GLGizmoSeam.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoSimplify.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoEmboss.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoSVG.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoMeasure.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoText.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp"
#include "libslic3r/format.hpp"
@@ -152,7 +153,7 @@ void GLGizmosManager::switch_gizmos_icon_filename()
case(EType::Seam):
gizmo->set_icon_filename(m_is_dark ? "toolbar_seam_dark.svg" : "toolbar_seam.svg");
break;
case(EType::Text):
case(EType::Emboss):
gizmo->set_icon_filename(m_is_dark ? "toolbar_text_dark.svg" : "toolbar_text.svg");
break;
case(EType::MmuSegmentation):
@@ -198,7 +199,8 @@ bool GLGizmosManager::init()
m_gizmos.emplace_back(new GLGizmoMeshBoolean(m_parent, m_is_dark ? "toolbar_meshboolean_dark.svg" : "toolbar_meshboolean.svg", EType::MeshBoolean));
m_gizmos.emplace_back(new GLGizmoFdmSupports(m_parent, m_is_dark ? "toolbar_support_dark.svg" : "toolbar_support.svg", EType::FdmSupports));
m_gizmos.emplace_back(new GLGizmoSeam(m_parent, m_is_dark ? "toolbar_seam_dark.svg" : "toolbar_seam.svg", EType::Seam));
m_gizmos.emplace_back(new GLGizmoText(m_parent, m_is_dark ? "toolbar_text_dark.svg" : "toolbar_text.svg", EType::Text));
m_gizmos.emplace_back(new GLGizmoEmboss(m_parent, m_is_dark ? "toolbar_text_dark.svg" : "toolbar_text.svg", EType::Emboss));
m_gizmos.emplace_back(new GLGizmoSVG(m_parent));
m_gizmos.emplace_back(new GLGizmoMmuSegmentation(m_parent, m_is_dark ? "mmu_segmentation_dark.svg" : "mmu_segmentation.svg", EType::MmuSegmentation));
m_gizmos.emplace_back(new GLGizmoMeasure(m_parent, m_is_dark ? "toolbar_measure_dark.svg" : "toolbar_measure.svg", EType::Measure));
m_gizmos.emplace_back(new GLGizmoSimplify(m_parent, "reduce_triangles.svg", EType::Simplify));
@@ -251,27 +253,6 @@ bool GLGizmosManager::init_icon_textures()
else
return false;
if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/text_B.svg", 20, 20, texture_id))
icon_list.insert(std::make_pair((int)IC_TEXT_B, texture_id));
else
return false;
if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/text_B_dark.svg", 20, 20, texture_id))
icon_list.insert(std::make_pair((int)IC_TEXT_B_DARK, texture_id));
else
return false;
if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/text_T.svg", 20, 20, texture_id))
icon_list.insert(std::make_pair((int)IC_TEXT_T, texture_id));
else
return false;
if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/text_T_dark.svg", 20, 20, texture_id))
icon_list.insert(std::make_pair((int)IC_TEXT_T_DARK, texture_id));
else
return false;
return true;
}
@@ -328,7 +309,8 @@ void GLGizmosManager::reset_all_states()
open_gizmo(current);
activate_gizmo(Undefined);
m_hover = Undefined;
// Orca: do not clear hover state, as Emboss gizmo can be used without selection
//m_hover = Undefined;
}
bool GLGizmosManager::open_gizmo(EType type)
@@ -447,8 +429,6 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
return dynamic_cast<GLGizmoSeam*>(m_gizmos[Seam].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == MmuSegmentation)
return dynamic_cast<GLGizmoMmuSegmentation*>(m_gizmos[MmuSegmentation].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == Text)
return dynamic_cast<GLGizmoText*>(m_gizmos[Text].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == Measure)
return dynamic_cast<GLGizmoMeasure*>(m_gizmos[Measure].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == Cut)
@@ -609,7 +589,12 @@ bool GLGizmosManager::gizmos_toolbar_on_mouse(const wxMouseEvent &mouse_event) {
// mouse is above toolbar
if (mouse_event.LeftDown() || mouse_event.LeftDClick()) {
mc.left = true;
open_gizmo(gizmo);
if (gizmo == Emboss) {
GLGizmoBase *gizmo_emboss = m_gizmos[Emboss].get();
dynamic_cast<GLGizmoEmboss *>(gizmo_emboss)->on_shortcut_key();
} else {
open_gizmo(gizmo);
}
return true;
}
else if (mouse_event.RightDown()) {
@@ -1129,12 +1114,14 @@ void GLGizmosManager::do_render_overlay() const
const float v_bottom = v_top + dv - v_offset;
GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + icons_size_x, top_y - icons_size_y, top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } });
if (idx == m_current) {
if (idx == m_current
// Orca: Show Svg dialog at the same place as emboss gizmo
|| (m_current == Svg && idx == Emboss)) {
//BBS: GUI refactor: GLToolbar&&Gizmo adjust
//render_input_window uses a different coordination(imgui)
//1. no need to scale by camera zoom, set {0,0} at left-up corner for imgui
//gizmo->render_input_window(width, 0.5f * cnv_h - zoomed_top_y * zoom, toolbar_top);
gizmo->render_input_window(0.5 * cnv_w + 0.5f * top_x * cnv_w, get_scaled_total_height(), cnv_h);
m_gizmos[m_current]->render_input_window(0.5 * cnv_w + 0.5f * top_x * cnv_w, get_scaled_total_height(), cnv_h);
is_render_current = true;
}
@@ -1337,7 +1324,7 @@ std::string get_name_from_gizmo_etype(GLGizmosManager::EType type)
return "FdmSupports";
case GLGizmosManager::EType::Seam:
return "Seam";
case GLGizmosManager::EType::Text:
case GLGizmosManager::EType::Emboss:
return "Text";
case GLGizmosManager::EType::MmuSegmentation:
return "Color Painting";

View File

@@ -85,8 +85,8 @@ public:
MeshBoolean,
FdmSupports,
Seam,
// BBS
Text,
Emboss,
Svg,
MmuSegmentation,
Measure,
Simplify,
@@ -163,10 +163,6 @@ public:
IC_TOOLBAR_RESET_HOVER,
IC_TOOLBAR_TOOLTIP,
IC_TOOLBAR_TOOLTIP_HOVER,
IC_TEXT_B,
IC_TEXT_B_DARK,
IC_TEXT_T,
IC_TEXT_T_DARK,
IC_NAME_COUNT,
};

View File

@@ -1,3 +1,7 @@
///|/ Copyright (c) Prusa Research 2018 - 2023 Enrico Turri @enricoturri1966, Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Pavel Mikuš @Godrak, Filip Sykala @Jony01, Vojtěch Bubník @bubnikv, Vojtěch Král @vojtechkral
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#include "slic3r/GUI/ImGuiWrapper.hpp"
#include <imgui/imgui_internal.h>
@@ -19,7 +23,7 @@
#include <boost/algorithm/string.hpp>
#define MAX_NUM 9999.99
#define MAX_SIZE "9999.99"
#define MAX_SIZE std::string_view{"9999.99"}
namespace Slic3r
{
@@ -81,7 +85,7 @@ void GizmoObjectManipulation::update_settings_value(const Selection& selection)
m_new_rotate_label_string = L("Rotation");
m_new_scale_label_string = L("Scale ratios");
m_world_coordinates = true;
m_coordinates_type = ECoordinatesType::World;
ObjectList* obj_list = wxGetApp().obj_list();
if (selection.is_single_full_instance()) {
@@ -89,7 +93,7 @@ void GizmoObjectManipulation::update_settings_value(const Selection& selection)
const GLVolume* volume = selection.get_first_volume();
m_new_position = volume->get_instance_offset();
if (m_world_coordinates) {
if (is_world_coordinates()) {
m_new_rotate_label_string = L("Rotate");
m_new_rotation = volume->get_instance_rotation() * (180. / M_PI);
m_new_size = selection.get_scaled_instance_bounding_box().size();
@@ -260,7 +264,15 @@ void GizmoObjectManipulation::change_position_value(int axis, double value)
Selection& selection = m_glcanvas.get_selection();
selection.setup_cache();
selection.translate(position - m_cache.position, selection.requires_local_axes());
TransformationType trafo_type;
trafo_type.set_relative();
switch (m_coordinates_type)
{
case ECoordinatesType::Instance: { trafo_type.set_instance(); break; }
case ECoordinatesType::Local: { trafo_type.set_local(); break; }
default: { break; }
}
selection.translate(position - m_cache.position, trafo_type);
m_glcanvas.do_move(L("Set Position"));
m_cache.position = position;
@@ -278,14 +290,16 @@ void GizmoObjectManipulation::change_rotation_value(int axis, double value)
Selection& selection = m_glcanvas.get_selection();
TransformationType transformation_type(TransformationType::World_Relative_Joint);
if (selection.is_single_full_instance() || selection.requires_local_axes())
transformation_type.set_independent();
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.
// transformation_type.set_absolute();
transformation_type.set_local();
}
TransformationType transformation_type;
transformation_type.set_relative();
if (selection.is_single_full_instance())
transformation_type.set_independent();
if (is_local_coordinates())
transformation_type.set_local();
if (is_instance_coordinates())
transformation_type.set_instance();
selection.setup_cache();
selection.rotate(
@@ -336,7 +350,7 @@ void GizmoObjectManipulation::change_size_value(int axis, double value)
ref_size = Vec3d(instance_scale[0] * ref_size[0], instance_scale[1] * ref_size[1], instance_scale[2] * ref_size[2]);
}
else if (selection.is_single_full_instance())
ref_size = m_world_coordinates ?
ref_size = is_world_coordinates() ?
selection.get_unscaled_instance_bounding_box().size() :
wxGetApp().model().objects[selection.get_first_volume()->object_idx()]->raw_mesh_bounding_box().size();
@@ -355,7 +369,7 @@ void GizmoObjectManipulation::do_scale(int axis, const Vec3d &scale) const
TransformationType transformation_type(TransformationType::World_Relative_Joint);
if (selection.is_single_full_instance()) {
transformation_type.set_absolute();
if (! m_world_coordinates)
if (! is_world_coordinates())
transformation_type.set_local();
}
@@ -364,7 +378,7 @@ void GizmoObjectManipulation::do_scale(int axis, const Vec3d &scale) const
scaling_factor = scale(axis) * Vec3d::Ones();
selection.setup_cache();
selection.scale(scaling_factor * 0.01, transformation_type);
selection.scale_legacy(scaling_factor * 0.01, transformation_type);
m_glcanvas.do_scale(L("Set Scale"));
}
@@ -386,6 +400,51 @@ void GizmoObjectManipulation::on_change(const std::string& opt_key, int axis, do
change_size_value(axis, new_value);
}
void GizmoObjectManipulation::set_uniform_scaling(const bool new_value)
{
const Selection &selection = m_glcanvas.get_selection();
if (selection.is_single_full_instance() && is_world_coordinates() && !new_value) {
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
// 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_first_volume();
// Is the angle close to a multiple of 90 degrees?
if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
// Cannot apply scaling in the world coordinate system.
// BBS: remove tilt prompt dialog
// Bake the rotation into the meshes of the object.
wxGetApp().model().objects[volume->composite_id.object_id]->bake_xy_rotation_into_meshes(volume->composite_id.instance_id);
// Update the 3D scene, selections etc.
wxGetApp().plater()->update();
// Recalculate cached values at this panel, refresh the screen.
this->UpdateAndShow(true);
}
}
m_uniform_scale = new_value;
}
void GizmoObjectManipulation::set_coordinates_type(ECoordinatesType type)
{
if (wxGetApp().get_mode() == comSimple)
type = ECoordinatesType::World;
if (m_coordinates_type == type)
return;
m_coordinates_type = type;
this->UpdateAndShow(true);
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
canvas->get_gizmos_manager().update_data();
canvas->set_as_dirty();
canvas->request_extra_frame();
}
ECoordinatesType GizmoObjectManipulation::get_coordinates_type() const
{
return m_coordinates_type;
}
void GizmoObjectManipulation::reset_position_value()
{
Selection& selection = m_glcanvas.get_selection();
@@ -427,7 +486,7 @@ void GizmoObjectManipulation::reset_rotation_value()
return;
// Update rotation at the GLVolumes.
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
selection.synchronize_unselected_volumes();
// Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
m_glcanvas.do_rotate(L("Reset Rotation"));
@@ -444,30 +503,6 @@ void GizmoObjectManipulation::reset_scale_value()
change_scale_value(2, 100.);
}
void GizmoObjectManipulation::set_uniform_scaling(const bool new_value)
{
const Selection &selection = m_glcanvas.get_selection();
if (selection.is_single_full_instance() && m_world_coordinates && !new_value) {
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
// 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_first_volume();
// Is the angle close to a multiple of 90 degrees?
if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
// Cannot apply scaling in the world coordinate system.
// BBS: remove tilt prompt dialog
// Bake the rotation into the meshes of the object.
wxGetApp().model().objects[volume->composite_id.object_id]->bake_xy_rotation_into_meshes(volume->composite_id.instance_id);
// Update the 3D scene, selections etc.
wxGetApp().plater()->update();
// Recalculate cached values at this panel, refresh the screen.
this->UpdateAndShow(true);
}
}
m_uniform_scale = new_value;
}
static const char* label_values[2][3] = {
{ "##position_x", "##position_y", "##position_z"},
{ "##rotation_x", "##rotation_y", "##rotation_z"}

View File

@@ -6,6 +6,8 @@
#include "libslic3r/Point.hpp"
#include <float.h>
#include "slic3r/GUI/GUI_Geometry.hpp"
//#include "slic3r/GUI/GLCanvas3D.hpp"
namespace Slic3r {
@@ -81,8 +83,7 @@ public:
Vec3d m_buffered_size;
bool m_new_enabled {true};
bool m_uniform_scale {true};
// Does the object manipulation panel work in World or Local coordinates?
bool m_world_coordinates = true;
ECoordinatesType m_coordinates_type{ ECoordinatesType::World };
bool m_show_clear_rotation { false };
bool m_show_clear_scale { false };
@@ -107,9 +108,12 @@ public:
void set_uniform_scaling(const bool uniform_scale);
bool get_uniform_scaling() const { return m_uniform_scale; }
// Does the object manipulation panel work in World or Local coordinates?
void set_world_coordinates(const bool world_coordinates) { m_world_coordinates = world_coordinates; this->UpdateAndShow(true); }
bool get_world_coordinates() const { return m_world_coordinates; }
void set_coordinates_type(ECoordinatesType type);
ECoordinatesType get_coordinates_type() const;
bool is_world_coordinates() const { return m_coordinates_type == ECoordinatesType::World; }
bool is_instance_coordinates() const { return m_coordinates_type == ECoordinatesType::Instance; }
bool is_local_coordinates() const { return m_coordinates_type == ECoordinatesType::Local; }
void reset_cache() { m_cache.reset(); }