mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-09 04:51:48 +08:00
Reorganize data structures
This commit is contained in:
parent
61fa3e8844
commit
574df48f85
@ -2,6 +2,7 @@
|
|||||||
#define slic3r_EmbossShape_hpp_
|
#define slic3r_EmbossShape_hpp_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
#include <cereal/cereal.hpp>
|
#include <cereal/cereal.hpp>
|
||||||
#include <cereal/types/string.hpp>
|
#include <cereal/types/string.hpp>
|
||||||
#include <cereal/types/optional.hpp>
|
#include <cereal/types/optional.hpp>
|
||||||
@ -12,6 +13,39 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
struct EmbossProjection
|
||||||
|
{
|
||||||
|
// Emboss depth, Size in local Z direction
|
||||||
|
double depth = 1.; // [in loacal mm]
|
||||||
|
// NOTE: User should see and modify mainly world size not local
|
||||||
|
|
||||||
|
// Flag that result volume use surface cutted from source objects
|
||||||
|
bool use_surface = false;
|
||||||
|
|
||||||
|
// enum class Align {
|
||||||
|
// left,
|
||||||
|
// right,
|
||||||
|
// center,
|
||||||
|
// top_left,
|
||||||
|
// top_right,
|
||||||
|
// top_center,
|
||||||
|
// bottom_left,
|
||||||
|
// bottom_right,
|
||||||
|
// bottom_center
|
||||||
|
// };
|
||||||
|
//// change pivot of volume
|
||||||
|
//// When not set, center is used and is not stored
|
||||||
|
// std::optional<Align> align;
|
||||||
|
|
||||||
|
// compare TextStyle
|
||||||
|
bool operator==(const EmbossProjection &other) const {
|
||||||
|
return depth == other.depth && use_surface == other.use_surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
// undo / redo stack recovery
|
||||||
|
template<class Archive> void serialize(Archive &ar) { ar(depth, use_surface); }
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contain plane shape information to be able emboss it and edit it
|
/// Contain plane shape information to be able emboss it and edit it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -23,18 +57,8 @@ struct EmbossShape
|
|||||||
// scale of shape, multiplier to get 3d point in mm from integer shape
|
// scale of shape, multiplier to get 3d point in mm from integer shape
|
||||||
double scale = 1.;
|
double scale = 1.;
|
||||||
|
|
||||||
// Emboss depth, Size in local Z direction
|
// Define how to emboss shape
|
||||||
double depth = 1.; // [in loacal mm]
|
EmbossProjection projection;
|
||||||
// NOTE: User should see and modify mainly world size not local
|
|
||||||
|
|
||||||
// Flag that result volume use surface cutted from source objects
|
|
||||||
bool use_surface = false;
|
|
||||||
|
|
||||||
// distance from surface point
|
|
||||||
// used for move over model surface
|
|
||||||
// When not set value is zero and is not stored
|
|
||||||
// NOTE: Can't be used together with use_surface
|
|
||||||
std::optional<float> distance; // [in mm]
|
|
||||||
|
|
||||||
// !!! Volume stored in .3mf has transformed vertices.
|
// !!! Volume stored in .3mf has transformed vertices.
|
||||||
// (baked transformation into vertices position)
|
// (baked transformation into vertices position)
|
||||||
@ -50,14 +74,12 @@ struct EmbossShape
|
|||||||
// undo / redo stack recovery
|
// undo / redo stack recovery
|
||||||
template<class Archive> void save(Archive &ar) const
|
template<class Archive> void save(Archive &ar) const
|
||||||
{
|
{
|
||||||
ar(shapes, scale, depth, use_surface, svg_file_path);
|
ar(shapes, scale, projection, svg_file_path);
|
||||||
cereal::save(ar, distance);
|
|
||||||
cereal::save(ar, fix_3mf_tr);
|
cereal::save(ar, fix_3mf_tr);
|
||||||
}
|
}
|
||||||
template<class Archive> void load(Archive &ar)
|
template<class Archive> void load(Archive &ar)
|
||||||
{
|
{
|
||||||
ar(shapes, scale, depth, use_surface, svg_file_path);
|
ar(shapes, scale, projection, svg_file_path);
|
||||||
cereal::load(ar, distance);
|
|
||||||
cereal::load(ar, fix_3mf_tr);
|
cereal::load(ar, fix_3mf_tr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -26,15 +26,6 @@ struct FontProp
|
|||||||
// When not set value is zero and is not stored
|
// When not set value is zero and is not stored
|
||||||
std::optional<int> line_gap; // [in font point]
|
std::optional<int> line_gap; // [in font point]
|
||||||
|
|
||||||
// Z depth of text
|
|
||||||
float emboss; // [in mm]
|
|
||||||
|
|
||||||
// Flag that text should use surface cutted from object
|
|
||||||
// FontProp::distance should without value
|
|
||||||
// FontProp::emboss should be positive number
|
|
||||||
// Note: default value is false
|
|
||||||
bool use_surface;
|
|
||||||
|
|
||||||
// positive value mean wider character shape
|
// positive value mean wider character shape
|
||||||
// negative value mean tiner character shape
|
// negative value mean tiner character shape
|
||||||
// When not set value is zero and is not stored
|
// When not set value is zero and is not stored
|
||||||
@ -45,35 +36,21 @@ struct FontProp
|
|||||||
// When not set value is zero and is not stored
|
// When not set value is zero and is not stored
|
||||||
std::optional<float> skew; // [ration x:y]
|
std::optional<float> skew; // [ration x:y]
|
||||||
|
|
||||||
// distance from surface point
|
|
||||||
// used for move over model surface
|
|
||||||
// When not set value is zero and is not stored
|
|
||||||
std::optional<float> distance; // [in mm]
|
|
||||||
|
|
||||||
// Angle of rotation around emboss direction (Z axis)
|
|
||||||
// It is calculate on the fly from volume world transformation
|
|
||||||
// only StyleManager keep actual value for comparision with style
|
|
||||||
// When not set value is zero and is not stored
|
|
||||||
std::optional<float> angle; // [in radians] form -Pi to Pi
|
|
||||||
|
|
||||||
// Parameter for True Type Font collections
|
// Parameter for True Type Font collections
|
||||||
// Select index of font in collection
|
// Select index of font in collection
|
||||||
std::optional<unsigned int> collection_number;
|
std::optional<unsigned int> collection_number;
|
||||||
|
|
||||||
//enum class Align {
|
[[deprecated("Back compatibility only, now it is stored EmbossProjection like depth")]]
|
||||||
// left,
|
float emboss;
|
||||||
// right,
|
|
||||||
// center,
|
[[deprecated("Back compatibility only, now it is stored EmbossProjection")]]
|
||||||
// top_left,
|
bool use_surface;
|
||||||
// top_right,
|
|
||||||
// top_center,
|
[[deprecated("it is calculated on the fly")]]
|
||||||
// bottom_left,
|
std::optional<float> distance;
|
||||||
// bottom_right,
|
|
||||||
// bottom_center
|
[[deprecated("it is calculated on the fly")]]
|
||||||
//};
|
std::optional<float> angle;
|
||||||
//// change pivot of text
|
|
||||||
//// When not set, center is used and is not stored
|
|
||||||
//std::optional<Align> align;
|
|
||||||
|
|
||||||
//////
|
//////
|
||||||
// Duplicit data to wxFontDescriptor
|
// Duplicit data to wxFontDescriptor
|
||||||
@ -104,45 +81,29 @@ struct FontProp
|
|||||||
return
|
return
|
||||||
char_gap == other.char_gap &&
|
char_gap == other.char_gap &&
|
||||||
line_gap == other.line_gap &&
|
line_gap == other.line_gap &&
|
||||||
use_surface == other.use_surface &&
|
|
||||||
is_approx(emboss, other.emboss) &&
|
|
||||||
is_approx(size_in_mm, other.size_in_mm) &&
|
is_approx(size_in_mm, other.size_in_mm) &&
|
||||||
is_approx(boldness, other.boldness) &&
|
is_approx(boldness, other.boldness) &&
|
||||||
is_approx(skew, other.skew) &&
|
is_approx(skew, other.skew);
|
||||||
is_approx(distance, other.distance) &&
|
|
||||||
is_approx(angle, other.angle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// undo / redo stack recovery
|
// undo / redo stack recovery
|
||||||
template<class Archive> void save(Archive &ar) const
|
template<class Archive> void save(Archive &ar) const
|
||||||
{
|
{
|
||||||
ar(emboss, use_surface, size_in_mm);
|
ar(size_in_mm);
|
||||||
cereal::save(ar, char_gap);
|
cereal::save(ar, char_gap);
|
||||||
cereal::save(ar, line_gap);
|
cereal::save(ar, line_gap);
|
||||||
cereal::save(ar, boldness);
|
cereal::save(ar, boldness);
|
||||||
cereal::save(ar, skew);
|
cereal::save(ar, skew);
|
||||||
cereal::save(ar, distance);
|
|
||||||
cereal::save(ar, angle);
|
|
||||||
cereal::save(ar, collection_number);
|
cereal::save(ar, collection_number);
|
||||||
cereal::save(ar, family);
|
|
||||||
cereal::save(ar, face_name);
|
|
||||||
cereal::save(ar, style);
|
|
||||||
cereal::save(ar, weight);
|
|
||||||
}
|
}
|
||||||
template<class Archive> void load(Archive &ar)
|
template<class Archive> void load(Archive &ar)
|
||||||
{
|
{
|
||||||
ar(emboss, use_surface, size_in_mm);
|
ar(size_in_mm);
|
||||||
cereal::load(ar, char_gap);
|
cereal::load(ar, char_gap);
|
||||||
cereal::load(ar, line_gap);
|
cereal::load(ar, line_gap);
|
||||||
cereal::load(ar, boldness);
|
cereal::load(ar, boldness);
|
||||||
cereal::load(ar, skew);
|
cereal::load(ar, skew);
|
||||||
cereal::load(ar, distance);
|
|
||||||
cereal::load(ar, angle);
|
|
||||||
cereal::load(ar, collection_number);
|
cereal::load(ar, collection_number);
|
||||||
cereal::load(ar, family);
|
|
||||||
cereal::load(ar, face_name);
|
|
||||||
cereal::load(ar, style);
|
|
||||||
cereal::load(ar, weight);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -196,9 +157,7 @@ struct EmbossStyle
|
|||||||
}
|
}
|
||||||
|
|
||||||
// undo / redo stack recovery
|
// undo / redo stack recovery
|
||||||
template<class Archive> void serialize(Archive &ar){
|
template<class Archive> void serialize(Archive &ar){ ar(name, path, type, prop); }
|
||||||
ar(name, path, type, prop);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Emboss style name inside vector is unique
|
// Emboss style name inside vector is unique
|
||||||
@ -219,21 +178,11 @@ struct TextConfiguration
|
|||||||
// Embossed text value
|
// Embossed text value
|
||||||
std::string text = "None";
|
std::string text = "None";
|
||||||
|
|
||||||
// !!! Volume stored in .3mf has transformed vertices.
|
[[deprecated("only for back compatibility, now it is stored in EmbossShape")]]
|
||||||
// (baked transformation into vertices position)
|
|
||||||
// Only place for fill this is when load from .3mf
|
|
||||||
// This is correct volume transformation
|
|
||||||
std::optional<Transform3d> fix_3mf_tr;
|
std::optional<Transform3d> fix_3mf_tr;
|
||||||
|
|
||||||
// undo / redo stack recovery
|
// undo / redo stack recovery
|
||||||
template<class Archive> void save(Archive &ar) const{
|
template<class Archive> void serialize(Archive &ar) { ar(style, text); }
|
||||||
ar(text, style);
|
|
||||||
cereal::save(ar, fix_3mf_tr);
|
|
||||||
}
|
|
||||||
template<class Archive> void load(Archive &ar){
|
|
||||||
ar(text, style);
|
|
||||||
cereal::load(ar, fix_3mf_tr);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -258,8 +258,6 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
Utils/Duet.hpp
|
Utils/Duet.hpp
|
||||||
Utils/EmbossStyleManager.cpp
|
Utils/EmbossStyleManager.cpp
|
||||||
Utils/EmbossStyleManager.hpp
|
Utils/EmbossStyleManager.hpp
|
||||||
Utils/EmbossStylesSerializable.cpp
|
|
||||||
Utils/EmbossStylesSerializable.hpp
|
|
||||||
Utils/FlashAir.cpp
|
Utils/FlashAir.cpp
|
||||||
Utils/FlashAir.hpp
|
Utils/FlashAir.hpp
|
||||||
Utils/FontConfigHelp.cpp
|
Utils/FontConfigHelp.cpp
|
||||||
|
@ -291,12 +291,9 @@ void CreateObjectJob::process(Ctl &ctl)
|
|||||||
if (!check(m_input))
|
if (!check(m_input))
|
||||||
throw JobException("Bad input data for EmbossCreateObjectJob.");
|
throw JobException("Bad input data for EmbossCreateObjectJob.");
|
||||||
|
|
||||||
if (m_input.base->shape.distance.has_value())
|
|
||||||
m_input.base->shape.distance.reset();
|
|
||||||
|
|
||||||
// can't create new object with using surface
|
// can't create new object with using surface
|
||||||
if (m_input.base->shape.use_surface)
|
if (m_input.base->shape.projection.use_surface)
|
||||||
m_input.base->shape.use_surface = false;
|
m_input.base->shape.projection.use_surface = false;
|
||||||
|
|
||||||
auto was_canceled = ::was_canceled(ctl, *m_input.base);
|
auto was_canceled = ::was_canceled(ctl, *m_input.base);
|
||||||
m_result = create_mesh(*m_input.base, was_canceled, ctl);
|
m_result = create_mesh(*m_input.base, was_canceled, ctl);
|
||||||
@ -319,7 +316,7 @@ void CreateObjectJob::process(Ctl &ctl)
|
|||||||
bed_coor = bed.centroid().cast<double>();
|
bed_coor = bed.centroid().cast<double>();
|
||||||
|
|
||||||
// TODO: need TextConfiguration refactor to work !!!
|
// TODO: need TextConfiguration refactor to work !!!
|
||||||
double z = m_input.base->shape.depth / 2;
|
double z = m_input.base->shape.projection.depth / 2;
|
||||||
|
|
||||||
Vec3d offset(bed_coor.x(), bed_coor.y(), z);
|
Vec3d offset(bed_coor.x(), bed_coor.y(), z);
|
||||||
offset -= m_result.center();
|
offset -= m_result.center();
|
||||||
@ -658,6 +655,8 @@ bool check(const DataCreateVolume &input, bool is_main_thread)
|
|||||||
assert(input.volume_type != ModelVolumeType::INVALID);
|
assert(input.volume_type != ModelVolumeType::INVALID);
|
||||||
res &= input.volume_type != ModelVolumeType::INVALID;
|
res &= input.volume_type != ModelVolumeType::INVALID;
|
||||||
res &= check(input.gizmo);
|
res &= check(input.gizmo);
|
||||||
|
assert(!input.base->shape.projection.use_surface);
|
||||||
|
res &= !input.base->shape.projection.use_surface;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
bool check(const DataCreateObject &input)
|
bool check(const DataCreateObject &input)
|
||||||
@ -673,6 +672,8 @@ bool check(const DataCreateObject &input)
|
|||||||
assert(input.bed_shape.size() >= 3); // at least triangle
|
assert(input.bed_shape.size() >= 3); // at least triangle
|
||||||
res &= input.bed_shape.size() >= 3;
|
res &= input.bed_shape.size() >= 3;
|
||||||
res &= check(input.gizmo);
|
res &= check(input.gizmo);
|
||||||
|
assert(!input.base->shape.projection.use_surface);
|
||||||
|
res &= !input.base->shape.projection.use_surface;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
bool check(const DataUpdate &input, bool is_main_thread, bool use_surface)
|
bool check(const DataUpdate &input, bool is_main_thread, bool use_surface)
|
||||||
@ -687,6 +688,8 @@ bool check(const DataUpdate &input, bool is_main_thread, bool use_surface)
|
|||||||
res &= input.base->cancel != nullptr;
|
res &= input.base->cancel != nullptr;
|
||||||
if (is_main_thread)
|
if (is_main_thread)
|
||||||
assert(!input.base->cancel->load());
|
assert(!input.base->cancel->load());
|
||||||
|
assert(!input.base->shape.projection.use_surface);
|
||||||
|
res &= !input.base->shape.projection.use_surface;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
bool check(const CreateSurfaceVolumeData &input, bool is_main_thread)
|
bool check(const CreateSurfaceVolumeData &input, bool is_main_thread)
|
||||||
@ -698,6 +701,8 @@ bool check(const CreateSurfaceVolumeData &input, bool is_main_thread)
|
|||||||
assert(!input.sources.empty());
|
assert(!input.sources.empty());
|
||||||
res &= !input.sources.empty();
|
res &= !input.sources.empty();
|
||||||
res &= check(input.gizmo);
|
res &= check(input.gizmo);
|
||||||
|
assert(input.base->shape.projection.use_surface);
|
||||||
|
res &= input.base->shape.projection.use_surface;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
bool check(const UpdateSurfaceVolumeData &input, bool is_main_thread)
|
bool check(const UpdateSurfaceVolumeData &input, bool is_main_thread)
|
||||||
@ -708,6 +713,8 @@ bool check(const UpdateSurfaceVolumeData &input, bool is_main_thread)
|
|||||||
res &= check(*input.base, is_main_thread, use_surface);
|
res &= check(*input.base, is_main_thread, use_surface);
|
||||||
assert(!input.sources.empty());
|
assert(!input.sources.empty());
|
||||||
res &= !input.sources.empty();
|
res &= !input.sources.empty();
|
||||||
|
assert(input.base->shape.projection.use_surface);
|
||||||
|
res &= input.base->shape.projection.use_surface;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,7 +723,7 @@ template<typename Fnc> TriangleMesh try_create_mesh(DataBase &base, const Fnc &w
|
|||||||
const EmbossShape &shape = base.create_shape();
|
const EmbossShape &shape = base.create_shape();
|
||||||
if (shape.shapes.empty())
|
if (shape.shapes.empty())
|
||||||
return {};
|
return {};
|
||||||
double depth = shape.depth / shape.scale;
|
double depth = shape.projection.depth / shape.scale;
|
||||||
auto projectZ = std::make_unique<ProjectZ>(depth);
|
auto projectZ = std::make_unique<ProjectZ>(depth);
|
||||||
ProjectScale project(std::move(projectZ), shape.scale);
|
ProjectScale project(std::move(projectZ), shape.scale);
|
||||||
if (was_canceled())
|
if (was_canceled())
|
||||||
@ -887,7 +894,7 @@ void create_volume(TriangleMesh &&mesh,
|
|||||||
if (trmat.has_value()) {
|
if (trmat.has_value()) {
|
||||||
volume->set_transformation(*trmat);
|
volume->set_transformation(*trmat);
|
||||||
} else {
|
} else {
|
||||||
assert(!data.shape.use_surface);
|
assert(!data.shape.projection.use_surface);
|
||||||
// Create transformation for volume near from object(defined by glVolume)
|
// Create transformation for volume near from object(defined by glVolume)
|
||||||
// Transformation is inspired add generic volumes in ObjectList::load_generic_subobject
|
// Transformation is inspired add generic volumes in ObjectList::load_generic_subobject
|
||||||
Vec3d volume_size = volume->mesh().bounding_box().size();
|
Vec3d volume_size = volume->mesh().bounding_box().size();
|
||||||
@ -1064,7 +1071,7 @@ template<typename Fnc> TriangleMesh cut_surface(DataBase &base, const SurfaceVol
|
|||||||
return {};
|
return {};
|
||||||
|
|
||||||
// !! Projection needs to transform cut
|
// !! Projection needs to transform cut
|
||||||
OrthoProject3d projection = create_emboss_projection(input2.is_outside, static_cast<float>(emboss_shape.depth), emboss_tr, cut);
|
OrthoProject3d projection = create_emboss_projection(input2.is_outside, static_cast<float>(emboss_shape.projection.depth), emboss_tr, cut);
|
||||||
indexed_triangle_set new_its = cut2model(cut, projection);
|
indexed_triangle_set new_its = cut2model(cut, projection);
|
||||||
assert(!new_its.empty());
|
assert(!new_its.empty());
|
||||||
if (was_canceled())
|
if (was_canceled())
|
||||||
@ -1132,7 +1139,7 @@ bool start_create_volume_job(Worker &worker,
|
|||||||
ModelVolumeType volume_type,
|
ModelVolumeType volume_type,
|
||||||
GLGizmosManager::EType gizmo)
|
GLGizmosManager::EType gizmo)
|
||||||
{
|
{
|
||||||
bool &use_surface = data->shape.use_surface;
|
bool &use_surface = data->shape.projection.use_surface;
|
||||||
std::unique_ptr<GUI::Job> job;
|
std::unique_ptr<GUI::Job> job;
|
||||||
if (use_surface) {
|
if (use_surface) {
|
||||||
// Model to cut surface from.
|
// Model to cut surface from.
|
||||||
@ -1211,8 +1218,8 @@ bool start_create_volume_on_surface_job(CreateVolumeParams &input, DataBasePtr d
|
|||||||
// soo create transfomation on border of object
|
// soo create transfomation on border of object
|
||||||
|
|
||||||
// there is no point on surface so no use of surface will be applied
|
// there is no point on surface so no use of surface will be applied
|
||||||
if (data_->shape.use_surface)
|
if (data_->shape.projection.use_surface)
|
||||||
data_->shape.use_surface = false;
|
data_->shape.projection.use_surface = false;
|
||||||
|
|
||||||
if (object == nullptr)
|
if (object == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
@ -168,7 +168,6 @@ SurfaceVolumeData::ModelSources create_volume_sources(const ModelVolume &volume)
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
struct CreateVolumeParams
|
struct CreateVolumeParams
|
||||||
{
|
{
|
||||||
|
|
||||||
GLCanvas3D &canvas;
|
GLCanvas3D &canvas;
|
||||||
|
|
||||||
// Direction of ray into scene
|
// Direction of ray into scene
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
#include "EmbossStyleManager.hpp"
|
#include "EmbossStyleManager.hpp"
|
||||||
|
#include <optional>
|
||||||
#include <GL/glew.h> // Imgui texture
|
#include <GL/glew.h> // Imgui texture
|
||||||
#include <imgui/imgui_internal.h> // ImTextCharFromUtf8
|
#include <imgui/imgui_internal.h> // ImTextCharFromUtf8
|
||||||
#include "WxFontUtils.hpp"
|
#include <libslic3r/AppConfig.hpp>
|
||||||
#include "libslic3r/Utils.hpp" // ScopeGuard
|
#include <libslic3r/Utils.hpp> // ScopeGuard
|
||||||
|
|
||||||
|
#include "WxFontUtils.hpp"
|
||||||
#include "slic3r/GUI/3DScene.hpp" // ::glsafe
|
#include "slic3r/GUI/3DScene.hpp" // ::glsafe
|
||||||
#include "slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp"
|
#include "slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp"
|
||||||
#include "slic3r/GUI/ImGuiWrapper.hpp" // check of font ranges
|
#include "slic3r/GUI/ImGuiWrapper.hpp" // check of font ranges
|
||||||
|
|
||||||
#include "slic3r/Utils/EmbossStylesSerializable.hpp"
|
|
||||||
|
|
||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
using namespace Slic3r::Emboss;
|
using namespace Slic3r::Emboss;
|
||||||
using namespace Slic3r::GUI::Emboss;
|
using namespace Slic3r::GUI::Emboss;
|
||||||
@ -28,11 +28,22 @@ StyleManager::~StyleManager() {
|
|||||||
free_style_images();
|
free_style_images();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For store/load emboss style to/from AppConfig
|
||||||
|
/// </summary>
|
||||||
|
namespace {
|
||||||
|
void store_style_index(AppConfig &cfg, unsigned index);
|
||||||
|
::std::optional<size_t> load_style_index(const AppConfig &cfg);
|
||||||
|
|
||||||
|
EmbossStyles load_styles(const AppConfig &cfg);
|
||||||
|
void store_styles(AppConfig &cfg, const EmbossStyles &styles);
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void StyleManager::init(AppConfig *app_config)
|
void StyleManager::init(AppConfig *app_config)
|
||||||
{
|
{
|
||||||
m_app_config = app_config;
|
m_app_config = app_config;
|
||||||
EmbossStyles styles = (app_config != nullptr) ?
|
EmbossStyles styles = (app_config != nullptr) ?
|
||||||
EmbossStylesSerializable::load_styles(*app_config) :
|
::load_styles(*app_config) :
|
||||||
EmbossStyles{};
|
EmbossStyles{};
|
||||||
if (styles.empty())
|
if (styles.empty())
|
||||||
styles = m_create_default_styles();
|
styles = m_create_default_styles();
|
||||||
@ -42,7 +53,7 @@ void StyleManager::init(AppConfig *app_config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<size_t> active_index_opt = (app_config != nullptr) ?
|
std::optional<size_t> active_index_opt = (app_config != nullptr) ?
|
||||||
EmbossStylesSerializable::load_style_index(*app_config) :
|
::load_style_index(*app_config) :
|
||||||
std::optional<size_t>{};
|
std::optional<size_t>{};
|
||||||
|
|
||||||
size_t active_index = 0;
|
size_t active_index = 0;
|
||||||
@ -83,13 +94,13 @@ bool StyleManager::store_styles_to_app_config(bool use_modification, bool store_
|
|||||||
size_t style_index = exist_stored_style() ?
|
size_t style_index = exist_stored_style() ?
|
||||||
m_style_cache.style_index :
|
m_style_cache.style_index :
|
||||||
m_last_style_index;
|
m_last_style_index;
|
||||||
EmbossStylesSerializable::store_style_index(*m_app_config, style_index);
|
store_style_index(*m_app_config, style_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
EmbossStyles styles;
|
EmbossStyles styles;
|
||||||
styles.reserve(m_style_items.size());
|
styles.reserve(m_style_items.size());
|
||||||
for (const Item &item : m_style_items) styles.push_back(item.style);
|
for (const Item &item : m_style_items) styles.push_back(item.style);
|
||||||
EmbossStylesSerializable::store_styles(*m_app_config, styles);
|
store_styles(*m_app_config, styles);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,3 +553,229 @@ bool StyleManager::set_wx_font(const wxFont &wx_font, std::unique_ptr<FontFile>
|
|||||||
clear_imgui_font();
|
clear_imgui_font();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <libslic3r/AppConfig.hpp>
|
||||||
|
#include "WxFontUtils.hpp"
|
||||||
|
#include "fast_float/fast_float.h"
|
||||||
|
|
||||||
|
// StylesSerializable
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace Slic3r;
|
||||||
|
using namespace Slic3r::GUI;
|
||||||
|
using Section = std::map<std::string,std::string>;
|
||||||
|
|
||||||
|
const std::string APP_CONFIG_FONT_NAME = "name";
|
||||||
|
const std::string APP_CONFIG_FONT_DESCRIPTOR = "descriptor";
|
||||||
|
const std::string APP_CONFIG_FONT_LINE_HEIGHT = "line_height";
|
||||||
|
const std::string APP_CONFIG_FONT_DEPTH = "depth";
|
||||||
|
const std::string APP_CONFIG_FONT_USE_SURFACE = "use_surface";
|
||||||
|
const std::string APP_CONFIG_FONT_BOLDNESS = "boldness";
|
||||||
|
const std::string APP_CONFIG_FONT_SKEW = "skew";
|
||||||
|
const std::string APP_CONFIG_FONT_DISTANCE = "distance";
|
||||||
|
const std::string APP_CONFIG_FONT_ANGLE = "angle";
|
||||||
|
const std::string APP_CONFIG_FONT_COLLECTION = "collection";
|
||||||
|
const std::string APP_CONFIG_FONT_CHAR_GAP = "char_gap";
|
||||||
|
const std::string APP_CONFIG_FONT_LINE_GAP = "line_gap";
|
||||||
|
|
||||||
|
const std::string APP_CONFIG_ACTIVE_FONT = "active_font";
|
||||||
|
|
||||||
|
std::string create_section_name(unsigned index)
|
||||||
|
{
|
||||||
|
return AppConfig::SECTION_EMBOSS_STYLE + ':' + std::to_string(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check only existence of flag
|
||||||
|
bool read(const Section §ion, const std::string &key, bool &value)
|
||||||
|
{
|
||||||
|
auto item = section.find(key);
|
||||||
|
if (item == section.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read(const Section §ion, const std::string &key, float &value)
|
||||||
|
{
|
||||||
|
auto item = section.find(key);
|
||||||
|
if (item == section.end())
|
||||||
|
return false;
|
||||||
|
const std::string &data = item->second;
|
||||||
|
if (data.empty())
|
||||||
|
return false;
|
||||||
|
float value_;
|
||||||
|
fast_float::from_chars(data.c_str(), data.c_str() + data.length(), value_);
|
||||||
|
// read only non zero value
|
||||||
|
if (fabs(value_) <= std::numeric_limits<float>::epsilon())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = value_;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read(const Section §ion, const std::string &key, std::optional<int> &value)
|
||||||
|
{
|
||||||
|
auto item = section.find(key);
|
||||||
|
if (item == section.end())
|
||||||
|
return false;
|
||||||
|
const std::string &data = item->second;
|
||||||
|
if (data.empty())
|
||||||
|
return false;
|
||||||
|
int value_ = std::atoi(data.c_str());
|
||||||
|
if (value_ == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = value_;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read(const Section §ion, const std::string &key, std::optional<unsigned int> &value)
|
||||||
|
{
|
||||||
|
auto item = section.find(key);
|
||||||
|
if (item == section.end())
|
||||||
|
return false;
|
||||||
|
const std::string &data = item->second;
|
||||||
|
if (data.empty())
|
||||||
|
return false;
|
||||||
|
int value_ = std::atoi(data.c_str());
|
||||||
|
if (value_ <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = static_cast<unsigned int>(value_);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read(const Section §ion, const std::string &key, std::optional<float> &value)
|
||||||
|
{
|
||||||
|
auto item = section.find(key);
|
||||||
|
if (item == section.end())
|
||||||
|
return false;
|
||||||
|
const std::string &data = item->second;
|
||||||
|
if (data.empty())
|
||||||
|
return false;
|
||||||
|
float value_;
|
||||||
|
fast_float::from_chars(data.c_str(), data.c_str() + data.length(), value_);
|
||||||
|
// read only non zero value
|
||||||
|
if (fabs(value_) <= std::numeric_limits<float>::epsilon())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = value_;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<EmbossStyle> load_style(const Section &app_cfg_section)
|
||||||
|
{
|
||||||
|
auto path_it = app_cfg_section.find(APP_CONFIG_FONT_DESCRIPTOR);
|
||||||
|
if (path_it == app_cfg_section.end())
|
||||||
|
return {};
|
||||||
|
const std::string &path = path_it->second;
|
||||||
|
|
||||||
|
auto name_it = app_cfg_section.find(APP_CONFIG_FONT_NAME);
|
||||||
|
const std::string default_name = "font_name";
|
||||||
|
const std::string &name = (name_it == app_cfg_section.end()) ? default_name : name_it->second;
|
||||||
|
|
||||||
|
FontProp fp;
|
||||||
|
read(app_cfg_section, APP_CONFIG_FONT_LINE_HEIGHT, fp.size_in_mm);
|
||||||
|
read(app_cfg_section, APP_CONFIG_FONT_DEPTH, fp.emboss);
|
||||||
|
read(app_cfg_section, APP_CONFIG_FONT_USE_SURFACE, fp.use_surface);
|
||||||
|
read(app_cfg_section, APP_CONFIG_FONT_BOLDNESS, fp.boldness);
|
||||||
|
read(app_cfg_section, APP_CONFIG_FONT_SKEW, fp.skew);
|
||||||
|
read(app_cfg_section, APP_CONFIG_FONT_DISTANCE, fp.distance);
|
||||||
|
read(app_cfg_section, APP_CONFIG_FONT_ANGLE, fp.angle);
|
||||||
|
read(app_cfg_section, APP_CONFIG_FONT_COLLECTION, fp.collection_number);
|
||||||
|
read(app_cfg_section, APP_CONFIG_FONT_CHAR_GAP, fp.char_gap);
|
||||||
|
read(app_cfg_section, APP_CONFIG_FONT_LINE_GAP, fp.line_gap);
|
||||||
|
|
||||||
|
EmbossStyle::Type type = WxFontUtils::get_actual_type();
|
||||||
|
return EmbossStyle{name, path, type, fp};
|
||||||
|
}
|
||||||
|
|
||||||
|
void store_style(AppConfig &cfg, const EmbossStyle &fi, unsigned index)
|
||||||
|
{
|
||||||
|
Section data;
|
||||||
|
data[APP_CONFIG_FONT_NAME] = fi.name;
|
||||||
|
data[APP_CONFIG_FONT_DESCRIPTOR] = fi.path;
|
||||||
|
const FontProp &fp = fi.prop;
|
||||||
|
data[APP_CONFIG_FONT_LINE_HEIGHT] = std::to_string(fp.size_in_mm);
|
||||||
|
data[APP_CONFIG_FONT_DEPTH] = std::to_string(fp.emboss);
|
||||||
|
if (fp.use_surface)
|
||||||
|
data[APP_CONFIG_FONT_USE_SURFACE] = "true";
|
||||||
|
if (fp.boldness.has_value())
|
||||||
|
data[APP_CONFIG_FONT_BOLDNESS] = std::to_string(*fp.boldness);
|
||||||
|
if (fp.skew.has_value())
|
||||||
|
data[APP_CONFIG_FONT_SKEW] = std::to_string(*fp.skew);
|
||||||
|
if (fp.distance.has_value())
|
||||||
|
data[APP_CONFIG_FONT_DISTANCE] = std::to_string(*fp.distance);
|
||||||
|
if (fp.angle.has_value())
|
||||||
|
data[APP_CONFIG_FONT_ANGLE] = std::to_string(*fp.angle);
|
||||||
|
if (fp.collection_number.has_value())
|
||||||
|
data[APP_CONFIG_FONT_COLLECTION] = std::to_string(*fp.collection_number);
|
||||||
|
if (fp.char_gap.has_value())
|
||||||
|
data[APP_CONFIG_FONT_CHAR_GAP] = std::to_string(*fp.char_gap);
|
||||||
|
if (fp.line_gap.has_value())
|
||||||
|
data[APP_CONFIG_FONT_LINE_GAP] = std::to_string(*fp.line_gap);
|
||||||
|
cfg.set_section(create_section_name(index), std::move(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void store_style_index(AppConfig &cfg, unsigned index)
|
||||||
|
{
|
||||||
|
// store actual font index
|
||||||
|
// active font first index is +1 to correspond with section name
|
||||||
|
Section data;
|
||||||
|
data[APP_CONFIG_ACTIVE_FONT] = std::to_string(index);
|
||||||
|
cfg.set_section(AppConfig::SECTION_EMBOSS_STYLE, std::move(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<size_t> load_style_index(const AppConfig &cfg)
|
||||||
|
{
|
||||||
|
if (!cfg.has_section(AppConfig::SECTION_EMBOSS_STYLE))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto section = cfg.get_section(AppConfig::SECTION_EMBOSS_STYLE);
|
||||||
|
auto it = section.find(APP_CONFIG_ACTIVE_FONT);
|
||||||
|
if (it == section.end())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
size_t active_font = static_cast<size_t>(std::atoi(it->second.c_str()));
|
||||||
|
// order in config starts with number 1
|
||||||
|
return active_font - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmbossStyles load_styles(const AppConfig &cfg)
|
||||||
|
{
|
||||||
|
EmbossStyles result;
|
||||||
|
// human readable index inside of config starts from 1 !!
|
||||||
|
unsigned index = 1;
|
||||||
|
std::string section_name = create_section_name(index);
|
||||||
|
while (cfg.has_section(section_name)) {
|
||||||
|
std::optional<EmbossStyle> style_opt = load_style(cfg.get_section(section_name));
|
||||||
|
if (style_opt.has_value())
|
||||||
|
result.emplace_back(*style_opt);
|
||||||
|
section_name = create_section_name(++index);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void store_styles(AppConfig &cfg, const EmbossStyles &styles)
|
||||||
|
{
|
||||||
|
// store styles
|
||||||
|
unsigned index = 1;
|
||||||
|
for (const EmbossStyle &style : styles) {
|
||||||
|
// skip file paths + fonts from other OS(loaded from .3mf)
|
||||||
|
assert(style.type == WxFontUtils::get_actual_type());
|
||||||
|
// if (style_opt.type != WxFontUtils::get_actual_type()) continue;
|
||||||
|
store_style(cfg, style, index);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove rest of font sections (after deletation)
|
||||||
|
std::string section_name = create_section_name(index);
|
||||||
|
while (cfg.has_section(section_name)) {
|
||||||
|
cfg.clear_section(section_name);
|
||||||
|
section_name = create_section_name(index);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <libslic3r/BoundingBox.hpp>
|
#include <libslic3r/BoundingBox.hpp>
|
||||||
#include <libslic3r/Emboss.hpp>
|
#include <libslic3r/Emboss.hpp>
|
||||||
|
#include <libslic3r/TextConfiguration.hpp>
|
||||||
|
#include <libslic3r/EmbossShape.hpp>
|
||||||
#include <libslic3r/AppConfig.hpp>
|
#include <libslic3r/AppConfig.hpp>
|
||||||
|
|
||||||
namespace Slic3r::GUI::Emboss {
|
namespace Slic3r::GUI::Emboss {
|
||||||
@ -176,7 +178,9 @@ public:
|
|||||||
{
|
{
|
||||||
void* texture_id = 0; // GLuint
|
void* texture_id = 0; // GLuint
|
||||||
BoundingBox bounding_box;
|
BoundingBox bounding_box;
|
||||||
ImVec2 tex_size, uv0, uv1;
|
ImVec2 tex_size;
|
||||||
|
ImVec2 uv0;
|
||||||
|
ImVec2 uv1;
|
||||||
Point offset = Point(0, 0);
|
Point offset = Point(0, 0);
|
||||||
StyleImage() = default;
|
StyleImage() = default;
|
||||||
};
|
};
|
||||||
@ -187,9 +191,28 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
struct Item
|
struct Item
|
||||||
{
|
{
|
||||||
// define font, style and other property of text
|
// parent Text style
|
||||||
EmbossStyle style;
|
EmbossStyle style;
|
||||||
|
|
||||||
|
// Define how to emboss shape
|
||||||
|
EmbossProjection projection;
|
||||||
|
|
||||||
|
// distance from surface point
|
||||||
|
// used for move over model surface
|
||||||
|
// When not set value is zero and is not stored
|
||||||
|
std::optional<float> distance; // [in mm]
|
||||||
|
|
||||||
|
// Angle of rotation around emboss direction (Z axis)
|
||||||
|
// It is calculate on the fly from volume world transformation
|
||||||
|
// only StyleManager keep actual value for comparision with style
|
||||||
|
// When not set value is zero and is not stored
|
||||||
|
std::optional<float> angle; // [in radians] form -Pi to Pi
|
||||||
|
|
||||||
|
bool operator==(const Item &other) const
|
||||||
|
{
|
||||||
|
return style == other.style && projection == other.projection && distance == other.distance && angle == other.angle;
|
||||||
|
}
|
||||||
|
|
||||||
// cache for view font name with maximal width in imgui
|
// cache for view font name with maximal width in imgui
|
||||||
std::string truncated_name;
|
std::string truncated_name;
|
||||||
|
|
||||||
|
@ -1,201 +0,0 @@
|
|||||||
#include "EmbossStylesSerializable.hpp"
|
|
||||||
|
|
||||||
#include <libslic3r/AppConfig.hpp>
|
|
||||||
#include "WxFontUtils.hpp"
|
|
||||||
|
|
||||||
using namespace Slic3r;
|
|
||||||
using namespace Slic3r::GUI;
|
|
||||||
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_NAME = "name";
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_DESCRIPTOR = "descriptor";
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_LINE_HEIGHT = "line_height";
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_DEPTH = "depth";
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_USE_SURFACE = "use_surface";
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_BOLDNESS = "boldness";
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_SKEW = "skew";
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_DISTANCE = "distance";
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_ANGLE = "angle";
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_COLLECTION = "collection";
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_CHAR_GAP = "char_gap";
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_FONT_LINE_GAP = "line_gap";
|
|
||||||
|
|
||||||
const std::string EmbossStylesSerializable::APP_CONFIG_ACTIVE_FONT = "active_font";
|
|
||||||
|
|
||||||
std::string EmbossStylesSerializable::create_section_name(unsigned index)
|
|
||||||
{
|
|
||||||
return AppConfig::SECTION_EMBOSS_STYLE + ':' + std::to_string(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check only existence of flag
|
|
||||||
bool EmbossStylesSerializable::read(const std::map<std::string, std::string>& section, const std::string& key, bool& value){
|
|
||||||
auto item = section.find(key);
|
|
||||||
if (item == section.end()) return false;
|
|
||||||
|
|
||||||
value = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "fast_float/fast_float.h"
|
|
||||||
bool EmbossStylesSerializable::read(const std::map<std::string, std::string>& section, const std::string& key, float& value){
|
|
||||||
auto item = section.find(key);
|
|
||||||
if (item == section.end()) return false;
|
|
||||||
const std::string &data = item->second;
|
|
||||||
if (data.empty()) return false;
|
|
||||||
float value_;
|
|
||||||
fast_float::from_chars(data.c_str(), data.c_str() + data.length(), value_);
|
|
||||||
// read only non zero value
|
|
||||||
if (fabs(value_) <= std::numeric_limits<float>::epsilon()) return false;
|
|
||||||
|
|
||||||
value = value_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmbossStylesSerializable::read(const std::map<std::string, std::string>& section, const std::string& key, std::optional<int>& value){
|
|
||||||
auto item = section.find(key);
|
|
||||||
if (item == section.end()) return false;
|
|
||||||
const std::string &data = item->second;
|
|
||||||
if (data.empty()) return false;
|
|
||||||
int value_ = std::atoi(data.c_str());
|
|
||||||
if (value_ == 0) return false;
|
|
||||||
|
|
||||||
value = value_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmbossStylesSerializable::read(const std::map<std::string, std::string>& section, const std::string& key, std::optional<unsigned int>& value){
|
|
||||||
auto item = section.find(key);
|
|
||||||
if (item == section.end()) return false;
|
|
||||||
const std::string &data = item->second;
|
|
||||||
if (data.empty()) return false;
|
|
||||||
int value_ = std::atoi(data.c_str());
|
|
||||||
if (value_ <= 0) return false;
|
|
||||||
|
|
||||||
value = static_cast<unsigned int>(value_);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmbossStylesSerializable::read(const std::map<std::string, std::string>& section, const std::string& key, std::optional<float>& value){
|
|
||||||
auto item = section.find(key);
|
|
||||||
if (item == section.end()) return false;
|
|
||||||
const std::string &data = item->second;
|
|
||||||
if (data.empty()) return false;
|
|
||||||
float value_;
|
|
||||||
fast_float::from_chars(data.c_str(), data.c_str() + data.length(), value_);
|
|
||||||
// read only non zero value
|
|
||||||
if (fabs(value_) <= std::numeric_limits<float>::epsilon()) return false;
|
|
||||||
|
|
||||||
value = value_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<EmbossStyle> EmbossStylesSerializable::load_style(
|
|
||||||
const std::map<std::string, std::string> &app_cfg_section)
|
|
||||||
{
|
|
||||||
auto path_it = app_cfg_section.find(APP_CONFIG_FONT_DESCRIPTOR);
|
|
||||||
if (path_it == app_cfg_section.end()) return {};
|
|
||||||
const std::string &path = path_it->second;
|
|
||||||
|
|
||||||
auto name_it = app_cfg_section.find(APP_CONFIG_FONT_NAME);
|
|
||||||
const std::string default_name = "font_name";
|
|
||||||
const std::string &name =
|
|
||||||
(name_it == app_cfg_section.end()) ?
|
|
||||||
default_name : name_it->second;
|
|
||||||
|
|
||||||
FontProp fp;
|
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_LINE_HEIGHT, fp.size_in_mm);
|
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_DEPTH, fp.emboss);
|
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_USE_SURFACE, fp.use_surface);
|
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_BOLDNESS, fp.boldness);
|
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_SKEW, fp.skew);
|
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_DISTANCE, fp.distance);
|
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_ANGLE, fp.angle);
|
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_COLLECTION, fp.collection_number);
|
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_CHAR_GAP, fp.char_gap);
|
|
||||||
read(app_cfg_section, APP_CONFIG_FONT_LINE_GAP, fp.line_gap);
|
|
||||||
|
|
||||||
EmbossStyle::Type type = WxFontUtils::get_actual_type();
|
|
||||||
return EmbossStyle{ name, path, type, fp };
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmbossStylesSerializable::store_style(AppConfig & cfg,
|
|
||||||
const EmbossStyle &fi,
|
|
||||||
unsigned index)
|
|
||||||
{
|
|
||||||
std::map<std::string, std::string> data;
|
|
||||||
data[APP_CONFIG_FONT_NAME] = fi.name;
|
|
||||||
data[APP_CONFIG_FONT_DESCRIPTOR] = fi.path;
|
|
||||||
const FontProp &fp = fi.prop;
|
|
||||||
data[APP_CONFIG_FONT_LINE_HEIGHT] = std::to_string(fp.size_in_mm);
|
|
||||||
data[APP_CONFIG_FONT_DEPTH] = std::to_string(fp.emboss);
|
|
||||||
if (fp.use_surface)
|
|
||||||
data[APP_CONFIG_FONT_USE_SURFACE] = "true";
|
|
||||||
if (fp.boldness.has_value())
|
|
||||||
data[APP_CONFIG_FONT_BOLDNESS] = std::to_string(*fp.boldness);
|
|
||||||
if (fp.skew.has_value())
|
|
||||||
data[APP_CONFIG_FONT_SKEW] = std::to_string(*fp.skew);
|
|
||||||
if (fp.distance.has_value())
|
|
||||||
data[APP_CONFIG_FONT_DISTANCE] = std::to_string(*fp.distance);
|
|
||||||
if (fp.angle.has_value())
|
|
||||||
data[APP_CONFIG_FONT_ANGLE] = std::to_string(*fp.angle);
|
|
||||||
if (fp.collection_number.has_value())
|
|
||||||
data[APP_CONFIG_FONT_COLLECTION] = std::to_string(*fp.collection_number);
|
|
||||||
if (fp.char_gap.has_value())
|
|
||||||
data[APP_CONFIG_FONT_CHAR_GAP] = std::to_string(*fp.char_gap);
|
|
||||||
if (fp.line_gap.has_value())
|
|
||||||
data[APP_CONFIG_FONT_LINE_GAP] = std::to_string(*fp.line_gap);
|
|
||||||
cfg.set_section(create_section_name(index), std::move(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmbossStylesSerializable::store_style_index(AppConfig &cfg, unsigned index) {
|
|
||||||
// store actual font index
|
|
||||||
// active font first index is +1 to correspond with section name
|
|
||||||
std::map<std::string, std::string> data;
|
|
||||||
data[APP_CONFIG_ACTIVE_FONT] = std::to_string(index);
|
|
||||||
cfg.set_section(AppConfig::SECTION_EMBOSS_STYLE, std::move(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<size_t> EmbossStylesSerializable::load_style_index(const AppConfig &cfg)
|
|
||||||
{
|
|
||||||
if (!cfg.has_section(AppConfig::SECTION_EMBOSS_STYLE)) return {};
|
|
||||||
|
|
||||||
auto section = cfg.get_section(AppConfig::SECTION_EMBOSS_STYLE);
|
|
||||||
auto it = section.find(APP_CONFIG_ACTIVE_FONT);
|
|
||||||
if (it == section.end()) return {};
|
|
||||||
|
|
||||||
size_t active_font = static_cast<size_t>(std::atoi(it->second.c_str()));
|
|
||||||
// order in config starts with number 1
|
|
||||||
return active_font - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmbossStyles EmbossStylesSerializable::load_styles(const AppConfig &cfg)
|
|
||||||
{
|
|
||||||
EmbossStyles result;
|
|
||||||
// human readable index inside of config starts from 1 !!
|
|
||||||
unsigned index = 1;
|
|
||||||
std::string section_name = create_section_name(index);
|
|
||||||
while (cfg.has_section(section_name)) {
|
|
||||||
std::optional<EmbossStyle> style_opt = load_style(cfg.get_section(section_name));
|
|
||||||
if (style_opt.has_value()) result.emplace_back(*style_opt);
|
|
||||||
section_name = create_section_name(++index);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmbossStylesSerializable::store_styles(AppConfig &cfg, const EmbossStyles& styles)
|
|
||||||
{
|
|
||||||
// store styles
|
|
||||||
unsigned index = 1;
|
|
||||||
for (const EmbossStyle &style : styles) {
|
|
||||||
// skip file paths + fonts from other OS(loaded from .3mf)
|
|
||||||
assert(style.type == WxFontUtils::get_actual_type());
|
|
||||||
// if (style_opt.type != WxFontUtils::get_actual_type()) continue;
|
|
||||||
store_style(cfg, style, index++);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove rest of font sections (after deletation)
|
|
||||||
std::string section_name = create_section_name(index);
|
|
||||||
while (cfg.has_section(section_name)) {
|
|
||||||
cfg.clear_section(section_name);
|
|
||||||
section_name = create_section_name(++index);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
#ifndef slic3r_EmbossStylesSerializable_hpp_
|
|
||||||
#define slic3r_EmbossStylesSerializable_hpp_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <optional>
|
|
||||||
#include <libslic3r/TextConfiguration.hpp> // EmbossStyles+EmbossStyle
|
|
||||||
|
|
||||||
namespace Slic3r {
|
|
||||||
class AppConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Slic3r::GUI {
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// For store/load font list to/from AppConfig
|
|
||||||
/// </summary>
|
|
||||||
class EmbossStylesSerializable
|
|
||||||
{
|
|
||||||
static const std::string APP_CONFIG_FONT_NAME;
|
|
||||||
static const std::string APP_CONFIG_FONT_DESCRIPTOR;
|
|
||||||
static const std::string APP_CONFIG_FONT_LINE_HEIGHT;
|
|
||||||
static const std::string APP_CONFIG_FONT_DEPTH;
|
|
||||||
static const std::string APP_CONFIG_FONT_USE_SURFACE;
|
|
||||||
static const std::string APP_CONFIG_FONT_BOLDNESS;
|
|
||||||
static const std::string APP_CONFIG_FONT_SKEW;
|
|
||||||
static const std::string APP_CONFIG_FONT_DISTANCE;
|
|
||||||
static const std::string APP_CONFIG_FONT_ANGLE;
|
|
||||||
static const std::string APP_CONFIG_FONT_COLLECTION;
|
|
||||||
static const std::string APP_CONFIG_FONT_CHAR_GAP;
|
|
||||||
static const std::string APP_CONFIG_FONT_LINE_GAP;
|
|
||||||
|
|
||||||
static const std::string APP_CONFIG_ACTIVE_FONT;
|
|
||||||
public:
|
|
||||||
EmbossStylesSerializable() = delete;
|
|
||||||
|
|
||||||
static void store_style_index(AppConfig &cfg, unsigned index);
|
|
||||||
static std::optional<size_t> load_style_index(const AppConfig &cfg);
|
|
||||||
|
|
||||||
static EmbossStyles load_styles(const AppConfig &cfg);
|
|
||||||
static void store_styles(AppConfig &cfg, const EmbossStyles& styles);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::string create_section_name(unsigned index);
|
|
||||||
static std::optional<EmbossStyle> load_style(const std::map<std::string, std::string> &app_cfg_section);
|
|
||||||
static void store_style(AppConfig &cfg, const EmbossStyle &style, unsigned index);
|
|
||||||
|
|
||||||
// TODO: move to app config like read from section
|
|
||||||
static bool read(const std::map<std::string, std::string>& section, const std::string& key, bool& value);
|
|
||||||
static bool read(const std::map<std::string, std::string>& section, const std::string& key, float& value);
|
|
||||||
static bool read(const std::map<std::string, std::string>& section, const std::string& key, std::optional<int>& value);
|
|
||||||
static bool read(const std::map<std::string, std::string>& section, const std::string& key, std::optional<unsigned int>& value);
|
|
||||||
static bool read(const std::map<std::string, std::string>& section, const std::string& key, std::optional<float>& value);
|
|
||||||
};
|
|
||||||
} // namespace Slic3r
|
|
||||||
|
|
||||||
#endif // #define slic3r_EmbossStylesSerializable_hpp_
|
|
||||||
|
|
@ -512,7 +512,6 @@ TEST_CASE("UndoRedo TextConfiguration serialization", "[Emboss]")
|
|||||||
std::stringstream ss; // any stream can be used
|
std::stringstream ss; // any stream can be used
|
||||||
{
|
{
|
||||||
cereal::BinaryOutputArchive oarchive(ss); // Create an output archive
|
cereal::BinaryOutputArchive oarchive(ss); // Create an output archive
|
||||||
|
|
||||||
oarchive(tc);
|
oarchive(tc);
|
||||||
} // archive goes out of scope, ensuring all contents are flushed
|
} // archive goes out of scope, ensuring all contents are flushed
|
||||||
|
|
||||||
@ -532,9 +531,8 @@ TEST_CASE("UndoRedo EmbossShape serialization", "[Emboss]")
|
|||||||
EmbossShape emboss;
|
EmbossShape emboss;
|
||||||
emboss.shapes = {{{0, 0}, {10, 0}, {10, 10}, {0, 10}}, {{5, 5}, {6, 5}, {6, 6}, {5, 6}}};
|
emboss.shapes = {{{0, 0}, {10, 0}, {10, 10}, {0, 10}}, {{5, 5}, {6, 5}, {6, 6}, {5, 6}}};
|
||||||
emboss.scale = 2.;
|
emboss.scale = 2.;
|
||||||
emboss.depth = 5.;
|
emboss.projection.depth = 5.;
|
||||||
emboss.use_surface = true;
|
emboss.projection.use_surface = true;
|
||||||
emboss.distance = 3.f;
|
|
||||||
emboss.fix_3mf_tr = Transform3d::Identity();
|
emboss.fix_3mf_tr = Transform3d::Identity();
|
||||||
emboss.svg_file_path = "Everything starts somewhere, though many physicists disagree.\
|
emboss.svg_file_path = "Everything starts somewhere, though many physicists disagree.\
|
||||||
But people have always been dimly aware of the problem with the start of things.\
|
But people have always been dimly aware of the problem with the start of things.\
|
||||||
@ -543,7 +541,6 @@ TEST_CASE("UndoRedo EmbossShape serialization", "[Emboss]")
|
|||||||
std::stringstream ss; // any stream can be used
|
std::stringstream ss; // any stream can be used
|
||||||
{
|
{
|
||||||
cereal::BinaryOutputArchive oarchive(ss); // Create an output archive
|
cereal::BinaryOutputArchive oarchive(ss); // Create an output archive
|
||||||
|
|
||||||
oarchive(emboss);
|
oarchive(emboss);
|
||||||
} // archive goes out of scope, ensuring all contents are flushed
|
} // archive goes out of scope, ensuring all contents are flushed
|
||||||
|
|
||||||
@ -554,9 +551,8 @@ TEST_CASE("UndoRedo EmbossShape serialization", "[Emboss]")
|
|||||||
}
|
}
|
||||||
CHECK(emboss.shapes == emboss_loaded.shapes);
|
CHECK(emboss.shapes == emboss_loaded.shapes);
|
||||||
CHECK(emboss.scale == emboss_loaded.scale);
|
CHECK(emboss.scale == emboss_loaded.scale);
|
||||||
CHECK(emboss.depth == emboss_loaded.depth);
|
CHECK(emboss.projection.depth == emboss_loaded.projection.depth);
|
||||||
CHECK(emboss.use_surface == emboss_loaded.use_surface);
|
CHECK(emboss.projection.use_surface == emboss_loaded.projection.use_surface);
|
||||||
CHECK(emboss.distance == emboss_loaded.distance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user