mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-07 23:17:35 -06:00
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:
parent
7a8e1929ee
commit
933aa3050b
197 changed files with 27190 additions and 2454 deletions
|
@ -26,6 +26,8 @@
|
|||
#include "CustomGCode.hpp"
|
||||
#include "calib.hpp"
|
||||
#include "enum_bitmask.hpp"
|
||||
#include "TextConfiguration.hpp"
|
||||
#include "EmbossShape.hpp"
|
||||
|
||||
//BBS: add bbs 3mf
|
||||
#include "Format/bbs_3mf.hpp"
|
||||
|
@ -41,6 +43,7 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
namespace cereal {
|
||||
class BinaryInputArchive;
|
||||
|
@ -779,38 +782,6 @@ private:
|
|||
friend class ModelVolume;
|
||||
};
|
||||
|
||||
struct RaycastResult
|
||||
{
|
||||
Vec2d mouse_position = Vec2d::Zero();
|
||||
int mesh_id = -1;
|
||||
Vec3f hit = Vec3f::Zero();
|
||||
Vec3f normal = Vec3f::Zero();
|
||||
|
||||
template<typename Archive> void serialize(Archive &ar) { ar(mouse_position, mesh_id, hit, normal); }
|
||||
};
|
||||
|
||||
struct TextInfo
|
||||
{
|
||||
std::string m_font_name;
|
||||
float m_font_size = 16.f;
|
||||
int m_curr_font_idx = 0;
|
||||
bool m_bold = true;
|
||||
bool m_italic = false;
|
||||
float m_thickness = 2.f;
|
||||
float m_embeded_depth = 0.f;
|
||||
float m_rotate_angle = 0;
|
||||
float m_text_gap = 0.f;
|
||||
bool m_is_surface_text = false;
|
||||
bool m_keep_horizontal = false;
|
||||
std::string m_text;
|
||||
|
||||
RaycastResult m_rr;
|
||||
|
||||
template<typename Archive> void serialize(Archive &ar) {
|
||||
ar(m_font_name, m_font_size, m_curr_font_idx, m_bold, m_italic, m_thickness, m_embeded_depth, m_rotate_angle, m_text_gap, m_is_surface_text, m_keep_horizontal, m_text, m_rr);
|
||||
}
|
||||
};
|
||||
|
||||
// An object STL, or a modifier volume, over which a different set of parameters shall be applied.
|
||||
// ModelVolume instances are owned by a ModelObject.
|
||||
class ModelVolume final : public ObjectBase
|
||||
|
@ -829,7 +800,7 @@ public:
|
|||
bool is_converted_from_meters{ false };
|
||||
bool is_from_builtin_objects{ false };
|
||||
|
||||
template<class Archive> void serialize(Archive& ar) {
|
||||
template<class Archive> void serialize(Archive& ar) {
|
||||
//FIXME Vojtech: Serialize / deserialize only if the Source is set.
|
||||
// likely testing input_file or object_idx would be sufficient.
|
||||
ar(input_file, object_idx, volume_idx, mesh_offset, transform, is_converted_from_inches, is_converted_from_meters, is_from_builtin_objects);
|
||||
|
@ -883,7 +854,8 @@ public:
|
|||
void set_mesh(std::shared_ptr<const TriangleMesh> &mesh) { m_mesh = mesh; }
|
||||
void set_mesh(std::unique_ptr<const TriangleMesh> &&mesh) { m_mesh = std::move(mesh); }
|
||||
void reset_mesh() { m_mesh = std::make_shared<const TriangleMesh>(); }
|
||||
// Configuration parameters specific to an object model geometry or a modifier volume,
|
||||
const std::shared_ptr<const TriangleMesh>& get_mesh_shared_ptr() const { return m_mesh; }
|
||||
// Configuration parameters specific to an object model geometry or a modifier volume,
|
||||
// overriding the global Slic3r settings and the ModelObject settings.
|
||||
ModelConfigObject config;
|
||||
|
||||
|
@ -903,6 +875,14 @@ public:
|
|||
// List of exterior faces
|
||||
FacetsAnnotation exterior_facets;
|
||||
|
||||
// Is set only when volume is Embossed Text type
|
||||
// Contain information how to re-create volume
|
||||
std::optional<TextConfiguration> text_configuration;
|
||||
|
||||
// Is set only when volume is Embossed Shape
|
||||
// Contain 2d information about embossed shape to be editabled
|
||||
std::optional<EmbossShape> emboss_shape;
|
||||
|
||||
// A parent object owning this modifier volume.
|
||||
ModelObject* get_object() const { return this->object; }
|
||||
ModelVolumeType type() const { return m_type; }
|
||||
|
@ -913,6 +893,9 @@ public:
|
|||
bool is_support_enforcer() const { return m_type == ModelVolumeType::SUPPORT_ENFORCER; }
|
||||
bool is_support_blocker() const { return m_type == ModelVolumeType::SUPPORT_BLOCKER; }
|
||||
bool is_support_modifier() const { return m_type == ModelVolumeType::SUPPORT_BLOCKER || m_type == ModelVolumeType::SUPPORT_ENFORCER; }
|
||||
bool is_text() const { return text_configuration.has_value(); }
|
||||
bool is_svg() const { return emboss_shape.has_value() && !text_configuration.has_value(); }
|
||||
bool is_the_only_one_part() const; // behave like an object
|
||||
t_model_material_id material_id() const { return m_material_id; }
|
||||
void set_material_id(t_model_material_id material_id);
|
||||
void reset_extra_facets();
|
||||
|
@ -968,15 +951,16 @@ public:
|
|||
|
||||
const Geometry::Transformation& get_transformation() const { return m_transformation; }
|
||||
void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; }
|
||||
void set_transformation(const Transform3d &trafo) { m_transformation.set_from_transform(trafo); }
|
||||
void set_transformation(const Transform3d& trafo) { m_transformation.set_matrix(trafo); }
|
||||
|
||||
Vec3d get_offset() const { return m_transformation.get_offset(); }
|
||||
|
||||
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
|
||||
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }
|
||||
|
||||
void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); }
|
||||
void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); }
|
||||
|
||||
const Vec3d& get_rotation() const { return m_transformation.get_rotation(); }
|
||||
Vec3d get_rotation() const { return m_transformation.get_rotation(); }
|
||||
double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); }
|
||||
|
||||
void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); }
|
||||
|
@ -988,7 +972,7 @@ public:
|
|||
void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); }
|
||||
void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); }
|
||||
|
||||
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
|
||||
Vec3d get_mirror() const { return m_transformation.get_mirror(); }
|
||||
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
|
||||
bool is_left_handed() const { return m_transformation.is_left_handed(); }
|
||||
|
||||
|
@ -997,10 +981,8 @@ public:
|
|||
void convert_from_imperial_units();
|
||||
void convert_from_meters();
|
||||
|
||||
void set_text_info(const TextInfo& text_info) { m_text_info = text_info; }
|
||||
const TextInfo& get_text_info() const { return m_text_info; }
|
||||
|
||||
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
|
||||
const Transform3d& get_matrix() const { return m_transformation.get_matrix(); }
|
||||
Transform3d get_matrix_no_offset() const { return m_transformation.get_matrix_no_offset(); }
|
||||
|
||||
void set_new_unique_id() {
|
||||
ObjectBase::set_new_unique_id();
|
||||
|
@ -1044,8 +1026,6 @@ private:
|
|||
mutable Polygon m_cached_2d_polygon; //BBS, used for convex_hell_2d acceleration
|
||||
Geometry::Transformation m_transformation;
|
||||
|
||||
TextInfo m_text_info;
|
||||
|
||||
//BBS: add convex_hell_2d related logic
|
||||
void calculate_convex_hull_2d(const Geometry::Transformation &transformation) const;
|
||||
|
||||
|
@ -1100,10 +1080,10 @@ private:
|
|||
name(other.name), source(other.source), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull),
|
||||
config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation),
|
||||
supported_facets(other.supported_facets), seam_facets(other.seam_facets), mmu_segmentation_facets(other.mmu_segmentation_facets),
|
||||
m_text_info(other.m_text_info)
|
||||
cut_info(other.cut_info), text_configuration(other.text_configuration), emboss_shape(other.emboss_shape)
|
||||
{
|
||||
assert(this->id().valid());
|
||||
assert(this->config.id().valid());
|
||||
assert(this->id().valid());
|
||||
assert(this->config.id().valid());
|
||||
assert(this->supported_facets.id().valid());
|
||||
assert(this->seam_facets.id().valid());
|
||||
assert(this->mmu_segmentation_facets.id().valid());
|
||||
|
@ -1119,11 +1099,12 @@ private:
|
|||
this->set_material_id(other.material_id());
|
||||
}
|
||||
// Providing a new mesh, therefore this volume will get a new unique ID assigned.
|
||||
ModelVolume(ModelObject *object, const ModelVolume &other, const TriangleMesh &&mesh) :
|
||||
name(other.name), source(other.source), m_mesh(new TriangleMesh(std::move(mesh))), config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation)
|
||||
ModelVolume(ModelObject *object, const ModelVolume &other, TriangleMesh &&mesh) :
|
||||
name(other.name), source(other.source), config(other.config), object(object), m_mesh(new TriangleMesh(std::move(mesh))), m_type(other.m_type), m_transformation(other.m_transformation),
|
||||
cut_info(other.cut_info), text_configuration(other.text_configuration), emboss_shape(other.emboss_shape)
|
||||
{
|
||||
assert(this->id().valid());
|
||||
assert(this->config.id().valid());
|
||||
assert(this->id().valid());
|
||||
assert(this->config.id().valid());
|
||||
assert(this->supported_facets.id().valid());
|
||||
assert(this->seam_facets.id().valid());
|
||||
assert(this->mmu_segmentation_facets.id().valid());
|
||||
|
@ -1135,10 +1116,10 @@ private:
|
|||
assert(this->config.id() == other.config.id());
|
||||
this->set_material_id(other.material_id());
|
||||
this->config.set_new_unique_id();
|
||||
if (mesh.facets_count() > 1)
|
||||
if (m_mesh->facets_count() > 1)
|
||||
calculate_convex_hull();
|
||||
assert(this->config.id().valid());
|
||||
assert(this->config.id() != other.config.id());
|
||||
assert(this->config.id().valid());
|
||||
assert(this->config.id() != other.config.id());
|
||||
assert(this->supported_facets.id() != other.supported_facets.id());
|
||||
assert(this->seam_facets.id() != other.seam_facets.id());
|
||||
assert(this->mmu_segmentation_facets.id() != other.mmu_segmentation_facets.id());
|
||||
|
@ -1165,9 +1146,8 @@ private:
|
|||
// BBS: add backup, check modify
|
||||
bool mesh_changed = false;
|
||||
auto tr = m_transformation;
|
||||
ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull, m_text_info, cut_info);
|
||||
ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull, cut_info);
|
||||
mesh_changed |= !(tr == m_transformation);
|
||||
if (mesh_changed) m_transformation.get_matrix(true, true, true, true); // force dirty
|
||||
auto t = supported_facets.timestamp();
|
||||
cereal::load_by_value(ar, supported_facets);
|
||||
mesh_changed |= t != supported_facets.timestamp();
|
||||
|
@ -1178,6 +1158,8 @@ private:
|
|||
cereal::load_by_value(ar, mmu_segmentation_facets);
|
||||
mesh_changed |= t != mmu_segmentation_facets.timestamp();
|
||||
cereal::load_by_value(ar, config);
|
||||
cereal::load(ar, text_configuration);
|
||||
cereal::load(ar, emboss_shape);
|
||||
assert(m_mesh);
|
||||
if (has_convex_hull) {
|
||||
cereal::load_optional(ar, m_convex_hull);
|
||||
|
@ -1191,11 +1173,13 @@ private:
|
|||
}
|
||||
template<class Archive> void save(Archive &ar) const {
|
||||
bool has_convex_hull = m_convex_hull.get() != nullptr;
|
||||
ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull, m_text_info, cut_info);
|
||||
ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull, cut_info);
|
||||
cereal::save_by_value(ar, supported_facets);
|
||||
cereal::save_by_value(ar, seam_facets);
|
||||
cereal::save_by_value(ar, mmu_segmentation_facets);
|
||||
cereal::save_by_value(ar, config);
|
||||
cereal::save(ar, text_configuration);
|
||||
cereal::save(ar, emboss_shape);
|
||||
if (has_convex_hull)
|
||||
cereal::save_optional(ar, m_convex_hull);
|
||||
}
|
||||
|
@ -1259,7 +1243,7 @@ public:
|
|||
}
|
||||
void set_assemble_from_transform(Transform3d& transform) {
|
||||
m_assemble_initialized = true;
|
||||
m_assemble_transformation.set_from_transform(transform);
|
||||
m_assemble_transformation.set_matrix(transform);
|
||||
}
|
||||
void set_assemble_offset(const Vec3d& offset) { m_assemble_transformation.set_offset(offset); }
|
||||
void rotate_assemble(double angle, const Vec3d& axis) {
|
||||
|
@ -1270,13 +1254,13 @@ public:
|
|||
void set_offset_to_assembly(const Vec3d& offset) { m_offset_to_assembly = offset; }
|
||||
Vec3d get_offset_to_assembly() const { return m_offset_to_assembly; }
|
||||
|
||||
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
|
||||
Vec3d get_offset() const { return m_transformation.get_offset(); }
|
||||
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }
|
||||
|
||||
void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); }
|
||||
void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); }
|
||||
|
||||
const Vec3d& get_rotation() const { return m_transformation.get_rotation(); }
|
||||
Vec3d get_rotation() const { return m_transformation.get_rotation(); }
|
||||
double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); }
|
||||
|
||||
void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); }
|
||||
|
@ -1284,38 +1268,36 @@ public:
|
|||
|
||||
// BBS
|
||||
void rotate(Matrix3d rotation_matrix) {
|
||||
// note: must remove scaling from transformation, otherwise auto-orientation with scaled objects will have problem
|
||||
auto R = get_matrix(true,false,true).matrix().block<3, 3>(0, 0);
|
||||
auto R = m_transformation.get_rotation_matrix().matrix().block<3, 3>(0, 0);
|
||||
auto R_new = rotation_matrix * R;
|
||||
auto euler_angles = Geometry::extract_euler_angles(R_new);
|
||||
set_rotation(euler_angles);
|
||||
}
|
||||
|
||||
const Vec3d& get_scaling_factor() const { return m_transformation.get_scaling_factor(); }
|
||||
Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); }
|
||||
double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); }
|
||||
|
||||
void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); }
|
||||
void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); }
|
||||
|
||||
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
|
||||
Vec3d get_mirror() const { return m_transformation.get_mirror(); }
|
||||
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
|
||||
bool is_left_handed() const { return m_transformation.is_left_handed(); }
|
||||
bool is_left_handed() const { return m_transformation.is_left_handed(); }
|
||||
|
||||
void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); }
|
||||
void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); }
|
||||
|
||||
// To be called on an external mesh
|
||||
void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const;
|
||||
// Calculate a bounding box of a transformed mesh. To be called on an external mesh.
|
||||
BoundingBoxf3 transform_mesh_bounding_box(const TriangleMesh& mesh, bool dont_translate = false) const;
|
||||
// Transform an external bounding box.
|
||||
// Transform an external bounding box, thus the resulting bounding box is no more snug.
|
||||
BoundingBoxf3 transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate = false) const;
|
||||
// Transform an external vector.
|
||||
Vec3d transform_vector(const Vec3d& v, bool dont_translate = false) const;
|
||||
// To be called on an external polygon. It does not translate the polygon, only rotates and scales.
|
||||
void transform_polygon(Polygon* polygon) const;
|
||||
|
||||
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
|
||||
const Transform3d& get_matrix() const { return m_transformation.get_matrix(); }
|
||||
Transform3d get_matrix_no_offset() const { return m_transformation.get_matrix_no_offset(); }
|
||||
|
||||
bool is_printable() const { return object->printable && printable && (print_volume_state == ModelInstancePVS_Inside); }
|
||||
bool is_assemble_initialized() { return m_assemble_initialized; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue