mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-09 00:41:49 +08:00
Reorganize data structures
This commit is contained in:
parent
61fa3e8844
commit
574df48f85
@ -2,6 +2,7 @@
|
||||
#define slic3r_EmbossShape_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <cereal/types/string.hpp>
|
||||
#include <cereal/types/optional.hpp>
|
||||
@ -12,6 +13,39 @@
|
||||
|
||||
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>
|
||||
/// Contain plane shape information to be able emboss it and edit it
|
||||
/// </summary>
|
||||
@ -22,19 +56,9 @@ struct EmbossShape
|
||||
|
||||
// scale of shape, multiplier to get 3d point in mm from integer shape
|
||||
double scale = 1.;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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]
|
||||
// Define how to emboss shape
|
||||
EmbossProjection projection;
|
||||
|
||||
// !!! Volume stored in .3mf has transformed vertices.
|
||||
// (baked transformation into vertices position)
|
||||
@ -50,14 +74,12 @@ struct EmbossShape
|
||||
// undo / redo stack recovery
|
||||
template<class Archive> void save(Archive &ar) const
|
||||
{
|
||||
ar(shapes, scale, depth, use_surface, svg_file_path);
|
||||
cereal::save(ar, distance);
|
||||
ar(shapes, scale, projection, svg_file_path);
|
||||
cereal::save(ar, fix_3mf_tr);
|
||||
}
|
||||
template<class Archive> void load(Archive &ar)
|
||||
{
|
||||
ar(shapes, scale, depth, use_surface, svg_file_path);
|
||||
cereal::load(ar, distance);
|
||||
ar(shapes, scale, projection, svg_file_path);
|
||||
cereal::load(ar, fix_3mf_tr);
|
||||
}
|
||||
};
|
||||
|
@ -26,15 +26,6 @@ struct FontProp
|
||||
// When not set value is zero and is not stored
|
||||
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
|
||||
// negative value mean tiner character shape
|
||||
// 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
|
||||
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
|
||||
// Select index of font in collection
|
||||
std::optional<unsigned int> collection_number;
|
||||
|
||||
//enum class Align {
|
||||
// left,
|
||||
// right,
|
||||
// center,
|
||||
// top_left,
|
||||
// top_right,
|
||||
// top_center,
|
||||
// bottom_left,
|
||||
// bottom_right,
|
||||
// bottom_center
|
||||
//};
|
||||
//// change pivot of text
|
||||
//// When not set, center is used and is not stored
|
||||
//std::optional<Align> align;
|
||||
[[deprecated("Back compatibility only, now it is stored EmbossProjection like depth")]]
|
||||
float emboss;
|
||||
|
||||
[[deprecated("Back compatibility only, now it is stored EmbossProjection")]]
|
||||
bool use_surface;
|
||||
|
||||
[[deprecated("it is calculated on the fly")]]
|
||||
std::optional<float> distance;
|
||||
|
||||
[[deprecated("it is calculated on the fly")]]
|
||||
std::optional<float> angle;
|
||||
|
||||
//////
|
||||
// Duplicit data to wxFontDescriptor
|
||||
@ -104,45 +81,29 @@ struct FontProp
|
||||
return
|
||||
char_gap == other.char_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(boldness, other.boldness) &&
|
||||
is_approx(skew, other.skew) &&
|
||||
is_approx(distance, other.distance) &&
|
||||
is_approx(angle, other.angle);
|
||||
is_approx(skew, other.skew);
|
||||
}
|
||||
|
||||
// undo / redo stack recovery
|
||||
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, line_gap);
|
||||
cereal::save(ar, boldness);
|
||||
cereal::save(ar, skew);
|
||||
cereal::save(ar, distance);
|
||||
cereal::save(ar, angle);
|
||||
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)
|
||||
{
|
||||
ar(emboss, use_surface, size_in_mm);
|
||||
ar(size_in_mm);
|
||||
cereal::load(ar, char_gap);
|
||||
cereal::load(ar, line_gap);
|
||||
cereal::load(ar, boldness);
|
||||
cereal::load(ar, skew);
|
||||
cereal::load(ar, distance);
|
||||
cereal::load(ar, angle);
|
||||
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
|
||||
template<class Archive> void serialize(Archive &ar){
|
||||
ar(name, path, type, prop);
|
||||
}
|
||||
template<class Archive> void serialize(Archive &ar){ ar(name, path, type, prop); }
|
||||
};
|
||||
|
||||
// Emboss style name inside vector is unique
|
||||
@ -219,21 +178,11 @@ struct TextConfiguration
|
||||
// Embossed text value
|
||||
std::string text = "None";
|
||||
|
||||
// !!! Volume stored in .3mf has transformed vertices.
|
||||
// (baked transformation into vertices position)
|
||||
// Only place for fill this is when load from .3mf
|
||||
// This is correct volume transformation
|
||||
[[deprecated("only for back compatibility, now it is stored in EmbossShape")]]
|
||||
std::optional<Transform3d> fix_3mf_tr;
|
||||
|
||||
// undo / redo stack recovery
|
||||
template<class Archive> void save(Archive &ar) const{
|
||||
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);
|
||||
}
|
||||
template<class Archive> void serialize(Archive &ar) { ar(style, text); }
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -258,8 +258,6 @@ set(SLIC3R_GUI_SOURCES
|
||||
Utils/Duet.hpp
|
||||
Utils/EmbossStyleManager.cpp
|
||||
Utils/EmbossStyleManager.hpp
|
||||
Utils/EmbossStylesSerializable.cpp
|
||||
Utils/EmbossStylesSerializable.hpp
|
||||
Utils/FlashAir.cpp
|
||||
Utils/FlashAir.hpp
|
||||
Utils/FontConfigHelp.cpp
|
||||
|
@ -291,12 +291,9 @@ void CreateObjectJob::process(Ctl &ctl)
|
||||
if (!check(m_input))
|
||||
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
|
||||
if (m_input.base->shape.use_surface)
|
||||
m_input.base->shape.use_surface = false;
|
||||
if (m_input.base->shape.projection.use_surface)
|
||||
m_input.base->shape.projection.use_surface = false;
|
||||
|
||||
auto was_canceled = ::was_canceled(ctl, *m_input.base);
|
||||
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>();
|
||||
|
||||
// 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);
|
||||
offset -= m_result.center();
|
||||
@ -658,6 +655,8 @@ bool check(const DataCreateVolume &input, bool is_main_thread)
|
||||
assert(input.volume_type != ModelVolumeType::INVALID);
|
||||
res &= input.volume_type != ModelVolumeType::INVALID;
|
||||
res &= check(input.gizmo);
|
||||
assert(!input.base->shape.projection.use_surface);
|
||||
res &= !input.base->shape.projection.use_surface;
|
||||
return res;
|
||||
}
|
||||
bool check(const DataCreateObject &input)
|
||||
@ -673,6 +672,8 @@ bool check(const DataCreateObject &input)
|
||||
assert(input.bed_shape.size() >= 3); // at least triangle
|
||||
res &= input.bed_shape.size() >= 3;
|
||||
res &= check(input.gizmo);
|
||||
assert(!input.base->shape.projection.use_surface);
|
||||
res &= !input.base->shape.projection.use_surface;
|
||||
return res;
|
||||
}
|
||||
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;
|
||||
if (is_main_thread)
|
||||
assert(!input.base->cancel->load());
|
||||
assert(!input.base->shape.projection.use_surface);
|
||||
res &= !input.base->shape.projection.use_surface;
|
||||
return res;
|
||||
}
|
||||
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());
|
||||
res &= !input.sources.empty();
|
||||
res &= check(input.gizmo);
|
||||
assert(input.base->shape.projection.use_surface);
|
||||
res &= input.base->shape.projection.use_surface;
|
||||
return res;
|
||||
}
|
||||
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);
|
||||
assert(!input.sources.empty());
|
||||
res &= !input.sources.empty();
|
||||
assert(input.base->shape.projection.use_surface);
|
||||
res &= input.base->shape.projection.use_surface;
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -716,7 +723,7 @@ template<typename Fnc> TriangleMesh try_create_mesh(DataBase &base, const Fnc &w
|
||||
const EmbossShape &shape = base.create_shape();
|
||||
if (shape.shapes.empty())
|
||||
return {};
|
||||
double depth = shape.depth / shape.scale;
|
||||
double depth = shape.projection.depth / shape.scale;
|
||||
auto projectZ = std::make_unique<ProjectZ>(depth);
|
||||
ProjectScale project(std::move(projectZ), shape.scale);
|
||||
if (was_canceled())
|
||||
@ -887,7 +894,7 @@ void create_volume(TriangleMesh &&mesh,
|
||||
if (trmat.has_value()) {
|
||||
volume->set_transformation(*trmat);
|
||||
} else {
|
||||
assert(!data.shape.use_surface);
|
||||
assert(!data.shape.projection.use_surface);
|
||||
// Create transformation for volume near from object(defined by glVolume)
|
||||
// Transformation is inspired add generic volumes in ObjectList::load_generic_subobject
|
||||
Vec3d volume_size = volume->mesh().bounding_box().size();
|
||||
@ -1064,7 +1071,7 @@ template<typename Fnc> TriangleMesh cut_surface(DataBase &base, const SurfaceVol
|
||||
return {};
|
||||
|
||||
// !! 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);
|
||||
assert(!new_its.empty());
|
||||
if (was_canceled())
|
||||
@ -1132,7 +1139,7 @@ bool start_create_volume_job(Worker &worker,
|
||||
ModelVolumeType volume_type,
|
||||
GLGizmosManager::EType gizmo)
|
||||
{
|
||||
bool &use_surface = data->shape.use_surface;
|
||||
bool &use_surface = data->shape.projection.use_surface;
|
||||
std::unique_ptr<GUI::Job> job;
|
||||
if (use_surface) {
|
||||
// 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
|
||||
|
||||
// there is no point on surface so no use of surface will be applied
|
||||
if (data_->shape.use_surface)
|
||||
data_->shape.use_surface = false;
|
||||
if (data_->shape.projection.use_surface)
|
||||
data_->shape.projection.use_surface = false;
|
||||
|
||||
if (object == nullptr)
|
||||
return false;
|
||||
|
@ -168,7 +168,6 @@ SurfaceVolumeData::ModelSources create_volume_sources(const ModelVolume &volume)
|
||||
/// </summary>
|
||||
struct CreateVolumeParams
|
||||
{
|
||||
|
||||
GLCanvas3D &canvas;
|
||||
|
||||
// Direction of ray into scene
|
||||
|
@ -1,15 +1,15 @@
|
||||
#include "EmbossStyleManager.hpp"
|
||||
#include <optional>
|
||||
#include <GL/glew.h> // Imgui texture
|
||||
#include <imgui/imgui_internal.h> // ImTextCharFromUtf8
|
||||
#include "WxFontUtils.hpp"
|
||||
#include "libslic3r/Utils.hpp" // ScopeGuard
|
||||
#include <libslic3r/AppConfig.hpp>
|
||||
#include <libslic3r/Utils.hpp> // ScopeGuard
|
||||
|
||||
#include "WxFontUtils.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp" // ::glsafe
|
||||
#include "slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp"
|
||||
#include "slic3r/GUI/ImGuiWrapper.hpp" // check of font ranges
|
||||
|
||||
#include "slic3r/Utils/EmbossStylesSerializable.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Emboss;
|
||||
using namespace Slic3r::GUI::Emboss;
|
||||
@ -28,11 +28,22 @@ StyleManager::~StyleManager() {
|
||||
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)
|
||||
{
|
||||
m_app_config = app_config;
|
||||
EmbossStyles styles = (app_config != nullptr) ?
|
||||
EmbossStylesSerializable::load_styles(*app_config) :
|
||||
::load_styles(*app_config) :
|
||||
EmbossStyles{};
|
||||
if (styles.empty())
|
||||
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) ?
|
||||
EmbossStylesSerializable::load_style_index(*app_config) :
|
||||
::load_style_index(*app_config) :
|
||||
std::optional<size_t>{};
|
||||
|
||||
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() ?
|
||||
m_style_cache.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;
|
||||
styles.reserve(m_style_items.size());
|
||||
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;
|
||||
}
|
||||
|
||||
@ -542,3 +553,229 @@ bool StyleManager::set_wx_font(const wxFont &wx_font, std::unique_ptr<FontFile>
|
||||
clear_imgui_font();
|
||||
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 <libslic3r/BoundingBox.hpp>
|
||||
#include <libslic3r/Emboss.hpp>
|
||||
#include <libslic3r/TextConfiguration.hpp>
|
||||
#include <libslic3r/EmbossShape.hpp>
|
||||
#include <libslic3r/AppConfig.hpp>
|
||||
|
||||
namespace Slic3r::GUI::Emboss {
|
||||
@ -176,7 +178,9 @@ public:
|
||||
{
|
||||
void* texture_id = 0; // GLuint
|
||||
BoundingBox bounding_box;
|
||||
ImVec2 tex_size, uv0, uv1;
|
||||
ImVec2 tex_size;
|
||||
ImVec2 uv0;
|
||||
ImVec2 uv1;
|
||||
Point offset = Point(0, 0);
|
||||
StyleImage() = default;
|
||||
};
|
||||
@ -187,9 +191,28 @@ public:
|
||||
/// </summary>
|
||||
struct Item
|
||||
{
|
||||
// define font, style and other property of text
|
||||
// parent Text 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
|
||||
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_
|
||||
|
@ -511,8 +511,7 @@ TEST_CASE("UndoRedo TextConfiguration serialization", "[Emboss]")
|
||||
|
||||
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);
|
||||
} // archive goes out of scope, ensuring all contents are flushed
|
||||
|
||||
@ -532,9 +531,8 @@ TEST_CASE("UndoRedo EmbossShape serialization", "[Emboss]")
|
||||
EmbossShape emboss;
|
||||
emboss.shapes = {{{0, 0}, {10, 0}, {10, 10}, {0, 10}}, {{5, 5}, {6, 5}, {6, 6}, {5, 6}}};
|
||||
emboss.scale = 2.;
|
||||
emboss.depth = 5.;
|
||||
emboss.use_surface = true;
|
||||
emboss.distance = 3.f;
|
||||
emboss.projection.depth = 5.;
|
||||
emboss.projection.use_surface = true;
|
||||
emboss.fix_3mf_tr = Transform3d::Identity();
|
||||
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.\
|
||||
@ -543,7 +541,6 @@ TEST_CASE("UndoRedo EmbossShape serialization", "[Emboss]")
|
||||
std::stringstream ss; // any stream can be used
|
||||
{
|
||||
cereal::BinaryOutputArchive oarchive(ss); // Create an output archive
|
||||
|
||||
oarchive(emboss);
|
||||
} // 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.scale == emboss_loaded.scale);
|
||||
CHECK(emboss.depth == emboss_loaded.depth);
|
||||
CHECK(emboss.use_surface == emboss_loaded.use_surface);
|
||||
CHECK(emboss.distance == emboss_loaded.distance);
|
||||
CHECK(emboss.projection.depth == emboss_loaded.projection.depth);
|
||||
CHECK(emboss.projection.use_surface == emboss_loaded.projection.use_surface);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user