Merge branch 'tm_archive_registry_SPE-1676'

This commit is contained in:
tamasmeszaros 2023-05-10 15:59:43 +02:00
commit e3dcae6798
11 changed files with 285 additions and 205 deletions

View File

@ -131,6 +131,8 @@ set(SLIC3R_SOURCES
Format/AnycubicSLA.cpp
Format/STEP.hpp
Format/STEP.cpp
Format/SLAArchiveFormatRegistry.hpp
Format/SLAArchiveFormatRegistry.cpp
GCode/ThumbnailData.cpp
GCode/ThumbnailData.hpp
GCode/Thumbnails.cpp

View File

@ -4,44 +4,14 @@
#include <string>
#include "SLAArchiveWriter.hpp"
#include "SLAArchiveFormatRegistry.hpp"
#include "libslic3r/PrintConfig.hpp"
#define ANYCUBIC_SLA_FORMAT_VERSION_1 1
#define ANYCUBIC_SLA_FORMAT_VERSION_515 515
#define ANYCUBIC_SLA_FORMAT_VERSION_516 516
#define ANYCUBIC_SLA_FORMAT_VERSION_517 517
#define ANYCUBIC_SLA_FORMAT_VERSIONED(FILEFORMAT, NAME, VERSION) \
{ FILEFORMAT, { FILEFORMAT, [] (const auto &cfg) { return std::make_unique<AnycubicSLAArchive>(cfg, VERSION); } } }
#define ANYCUBIC_SLA_FORMAT(FILEFORMAT, NAME) \
ANYCUBIC_SLA_FORMAT_VERSIONED(FILEFORMAT, NAME, ANYCUBIC_SLA_FORMAT_VERSION_1)
/**
// Supports only ANYCUBIC_SLA_VERSION_1
ANYCUBIC_SLA_FORMAT_VERSIONED("pws", "Photon / Photon S", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("pw0", "Photon Zero", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("pwx", "Photon X", ANYCUBIC_SLA_VERSION_1),
// Supports ANYCUBIC_SLA_VERSION_1 and ANYCUBIC_SLA_VERSION_515
ANYCUBIC_SLA_FORMAT_VERSIONED("pwmo", "Photon Mono", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("pwms", "Photon Mono SE", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("dlp", "Photon Ultra", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("pwmx", "Photon Mono X", ANYCUBIC_SLA_VERSION_1),
ANYCUBIC_SLA_FORMAT_VERSIONED("pmsq", "Photon Mono SQ", ANYCUBIC_SLA_VERSION_1),
// Supports ANYCUBIC_SLA_VERSION_515 and ANYCUBIC_SLA_VERSION_516
ANYCUBIC_SLA_FORMAT_VERSIONED("pwma", "Photon Mono 4K", ANYCUBIC_SLA_VERSION_515),
ANYCUBIC_SLA_FORMAT_VERSIONED("pm3", "Photon M3", ANYCUBIC_SLA_VERSION_515),
ANYCUBIC_SLA_FORMAT_VERSIONED("pm3m", "Photon M3 Max", ANYCUBIC_SLA_VERSION_515),
// Supports NYCUBIC_SLA_VERSION_515 and ANYCUBIC_SLA_VERSION_516 and ANYCUBIC_SLA_VERSION_517
ANYCUBIC_SLA_FORMAT_VERSIONED("pwmb", "Photon Mono X 6K / Photon M3 Plus", ANYCUBIC_SLA_VERSION_515),
ANYCUBIC_SLA_FORMAT_VERSIONED("dl2p", "Photon Photon D2", ANYCUBIC_SLA_VERSION_515),
ANYCUBIC_SLA_FORMAT_VERSIONED("pmx2", "Photon Mono X2", ANYCUBIC_SLA_VERSION_515),
ANYCUBIC_SLA_FORMAT_VERSIONED("pm3r", "Photon M3 Premium", ANYCUBIC_SLA_VERSION_515),
*/
constexpr uint16_t ANYCUBIC_SLA_FORMAT_VERSION_1 = 1;
constexpr uint16_t ANYCUBIC_SLA_FORMAT_VERSION_515 = 515;
constexpr uint16_t ANYCUBIC_SLA_FORMAT_VERSION_516 = 516;
constexpr uint16_t ANYCUBIC_SLA_FORMAT_VERSION_517 = 517;
namespace Slic3r {
@ -75,6 +45,21 @@ public:
const std::string &projectname = "") override;
};
inline Slic3r::ArchiveEntry anycubic_sla_format_versioned(const char *fileformat, const char *desc, uint16_t version)
{
Slic3r::ArchiveEntry entry(fileformat);
entry.desc = desc;
entry.ext = fileformat;
entry.wrfactoryfn = [version] (const auto &cfg) { return std::make_unique<AnycubicSLAArchive>(cfg, version); };
return entry;
}
inline Slic3r::ArchiveEntry anycubic_sla_format(const char *fileformat, const char *desc)
{
return anycubic_sla_format_versioned(fileformat, desc, ANYCUBIC_SLA_FORMAT_VERSION_1);
}
} // namespace Slic3r::sla

View File

@ -17,6 +17,7 @@
#include "libslic3r/GCode/ThumbnailData.hpp"
#include "SLAArchiveReader.hpp"
#include "SLAArchiveFormatRegistry.hpp"
#include "ZipperArchiveImport.hpp"
#include "libslic3r/MarchingSquares.hpp"
@ -26,6 +27,7 @@
#include "libslic3r/SLA/RasterBase.hpp"
#include <boost/property_tree/ini_parser.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/algorithm/string.hpp>

View File

@ -0,0 +1,147 @@
#include <set>
#include <mutex>
#include <memory>
#include "SL1.hpp"
#include "SL1_SVG.hpp"
#include "AnycubicSLA.hpp"
#include "SLAArchiveFormatRegistry.hpp"
namespace Slic3r {
static std::mutex arch_mtx;
class Registry {
static std::unique_ptr<Registry> registry;
std::set<ArchiveEntry> entries;
public:
Registry ()
{
entries = {
{
"SL1", // id
L("SL1 archive format"), // description
"sl1", // main extension
{"sl1s", "zip"}, // extension aliases
// Writer factory
[] (const auto &cfg) { return std::make_unique<SL1Archive>(cfg); },
// Reader factory
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) {
return std::make_unique<SL1Reader>(fname, quality, progr);
}
},
{
"SL1SVG",
L("SL1SVG archive files"),
"sl1_svg",
{},
[] (const auto &cfg) { return std::make_unique<SL1_SVGArchive>(cfg); },
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) {
return std::make_unique<SL1_SVGReader>(fname, quality, progr);
}
},
{
"SL2",
"",
"sl1_svg",
{},
[] (const auto &cfg) { return std::make_unique<SL1_SVGArchive>(cfg); },
nullptr
},
anycubic_sla_format("pwmo", "Photon Mono"),
anycubic_sla_format("pwmx", "Photon Mono X"),
anycubic_sla_format("pwms", "Photon Mono SE"),
/**
// Supports only ANYCUBIC_SLA_VERSION_1
anycubic_sla_format_versioned("pws", "Photon / Photon S", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("pw0", "Photon Zero", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("pwx", "Photon X", ANYCUBIC_SLA_VERSION_1),
// Supports ANYCUBIC_SLA_VERSION_1 and ANYCUBIC_SLA_VERSION_515
anycubic_sla_format_versioned("pwmo", "Photon Mono", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("pwms", "Photon Mono SE", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("dlp", "Photon Ultra", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("pwmx", "Photon Mono X", ANYCUBIC_SLA_VERSION_1),
anycubic_sla_format_versioned("pmsq", "Photon Mono SQ", ANYCUBIC_SLA_VERSION_1),
// Supports ANYCUBIC_SLA_VERSION_515 and ANYCUBIC_SLA_VERSION_516
anycubic_sla_format_versioned("pwma", "Photon Mono 4K", ANYCUBIC_SLA_VERSION_515),
anycubic_sla_format_versioned("pm3", "Photon M3", ANYCUBIC_SLA_VERSION_515),
anycubic_sla_format_versioned("pm3m", "Photon M3 Max", ANYCUBIC_SLA_VERSION_515),
// Supports NYCUBIC_SLA_VERSION_515 and ANYCUBIC_SLA_VERSION_516 and ANYCUBIC_SLA_VERSION_517
anycubic_sla_format_versioned("pwmb", "Photon Mono X 6K / Photon M3 Plus", ANYCUBIC_SLA_VERSION_515),
anycubic_sla_format_versioned("dl2p", "Photon Photon D2", ANYCUBIC_SLA_VERSION_515),
anycubic_sla_format_versioned("pmx2", "Photon Mono X2", ANYCUBIC_SLA_VERSION_515),
anycubic_sla_format_versioned("pm3r", "Photon M3 Premium", ANYCUBIC_SLA_VERSION_515),
*/
};
}
static Registry& get_instance()
{
if (!registry)
registry = std::make_unique<Registry>();
return *registry;
}
static std::set<ArchiveEntry>& get()
{
return get_instance().entries;
}
std::set<ArchiveEntry>& get_entries() { return entries; }
};
std::unique_ptr<Registry> Registry::registry = nullptr;
std::set<ArchiveEntry> registered_sla_archives()
{
std::lock_guard lk{arch_mtx};
return Registry::get();
}
std::vector<std::string> get_extensions(const ArchiveEntry &entry)
{
auto ret = reserve_vector<std::string>(entry.ext_aliases.size() + 1);
ret.emplace_back(entry.ext);
for (const char *alias : entry.ext_aliases)
ret.emplace_back(alias);
return ret;
}
ArchiveWriterFactory get_writer_factory(const char *formatid)
{
std::lock_guard lk{arch_mtx};
ArchiveWriterFactory ret;
auto entry = Registry::get().find(ArchiveEntry{formatid});
if (entry != Registry::get().end())
ret = entry->wrfactoryfn;
return ret;
}
ArchiveReaderFactory get_reader_factory(const char *formatid)
{
std::lock_guard lk{arch_mtx};
ArchiveReaderFactory ret;
auto entry = Registry::get().find(ArchiveEntry{formatid});
if (entry != Registry::get().end())
ret = entry->rdfactoryfn;
return ret;
}
} // namespace Slic3r::sla

View File

@ -0,0 +1,71 @@
#ifndef SLA_ARCHIVE_FORMAT_REGISTRY_HPP
#define SLA_ARCHIVE_FORMAT_REGISTRY_HPP
#include "SLAArchiveWriter.hpp"
#include "SLAArchiveReader.hpp"
#include <cstring>
namespace Slic3r {
// Factory function that returns an implementation of SLAArchiveWriter given
// a printer configuration.
using ArchiveWriterFactory = std::function<
std::unique_ptr<SLAArchiveWriter>(const SLAPrinterConfig &)
>;
// Factory function that returns an implementation of SLAArchiveReader
using ArchiveReaderFactory = std::function<
std::unique_ptr<SLAArchiveReader>(const std::string &fname,
SLAImportQuality quality,
const ProgrFn & progr)
>;
struct ArchiveEntry {
// Main ID for the format, for internal unique identification
const char *id;
// Generic description (usable in GUI) about an archive format. Should only
// be marked for localization (macro L).
const char *desc = "";
// Main extension of the format.
const char *ext = "zip";
ArchiveWriterFactory wrfactoryfn;
ArchiveReaderFactory rdfactoryfn;
// Secondary, alias extensions
std::vector<const char *> ext_aliases;
explicit ArchiveEntry(const char *formatid) : id{formatid} {}
ArchiveEntry(const char *formatid,
const char *description,
const char *extension,
std::initializer_list<const char *> extaliases,
const ArchiveWriterFactory &wrfn,
const ArchiveReaderFactory &rdfn)
: id{formatid}
, desc{description}
, ext{extension}
, ext_aliases{extaliases}
, wrfactoryfn{wrfn}
, rdfactoryfn{rdfn}
{}
bool operator <(const ArchiveEntry &other) const
{
return std::strcmp(id, other.id) < 0;
}
};
std::vector<std::string> get_extensions(const ArchiveEntry &entry);
std::set<ArchiveEntry> registered_sla_archives();
ArchiveWriterFactory get_writer_factory(const char *formatid);
ArchiveReaderFactory get_reader_factory(const char *formatid);
} // namespace Slic3r
#endif // ARCHIVEREGISTRY_HPP

View File

@ -8,44 +8,13 @@
#include <boost/filesystem/path.hpp>
#include <boost/algorithm/string.hpp>
#include "SLAArchiveFormatRegistry.hpp"
#include <array>
#include <map>
namespace Slic3r {
namespace {
// Factory function that returns an implementation of SLAArchiveReader.
using ArchiveFactory = std::function<
std::unique_ptr<SLAArchiveReader>(const std::string &fname,
SLAImportQuality quality,
const ProgrFn & progr)>;
// Entry in the global registry of readable archive formats.
struct ArchiveEntry {
const char *descr;
std::vector<const char *> extensions;
ArchiveFactory factoryfn;
};
// This is where the readable archive formats are registered.
static const std::map<std::string, ArchiveEntry> REGISTERED_ARCHIVES {
{
"SL1",
{ L("SL1 / SL1S archive files"), {"sl1", "sl1s", "zip"},
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) { return std::make_unique<SL1Reader>(fname, quality, progr); } }
},
{
"SL1SVG",
{ L("SL1SVG archive files"), {"sl1_svg"/*, "zip"*/}, // also a zip but unnecessary hassle to implement single extension for multiple archives
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) { return std::make_unique<SL1_SVGReader>(fname, quality, progr); }}
},
// TODO: pwmx and future others.
};
} // namespace
std::unique_ptr<SLAArchiveReader> SLAArchiveReader::create(
const std::string &fname,
const std::string &format_id,
@ -64,11 +33,13 @@ std::unique_ptr<SLAArchiveReader> SLAArchiveReader::create(
std::unique_ptr<SLAArchiveReader> ret;
auto arch_from = REGISTERED_ARCHIVES.begin();
auto arch_to = REGISTERED_ARCHIVES.end();
auto registry = registered_sla_archives();
auto arch_it = REGISTERED_ARCHIVES.find(format_id);
if (arch_it != REGISTERED_ARCHIVES.end()) {
auto arch_from = registry.begin();
auto arch_to = registry.end();
auto arch_it = registry.find(ArchiveEntry{format_id.c_str()});
if (arch_it != registry.end()) {
arch_from = arch_it;
arch_to = arch_it;
}
@ -77,52 +48,23 @@ std::unique_ptr<SLAArchiveReader> SLAArchiveReader::create(
if (ext.front() == '.')
ext.erase(ext.begin());
auto extcmp = [&ext](const auto &e) { return e == ext; };
for (auto it = arch_from; it != arch_to; ++it) {
const auto &[format_id, entry] = *it;
if (std::any_of(entry.extensions.begin(), entry.extensions.end(), extcmp))
ret = entry.factoryfn(fname, quality, progr);
for (auto it = arch_from; !ret && it != arch_to; ++it) {
const auto &entry = *it;
if (entry.rdfactoryfn) {
auto extensions = get_extensions(entry);
for (const std::string& supportedext : extensions) {
if (ext == supportedext) {
ret = entry.rdfactoryfn(fname, quality, progr);
break;
}
}
}
}
}
return ret;
}
const std::vector<const char *> &SLAArchiveReader::registered_archives()
{
static std::vector<const char*> archnames;
if (archnames.empty()) {
archnames.reserve(REGISTERED_ARCHIVES.size());
for (auto &[name, _] : REGISTERED_ARCHIVES)
archnames.emplace_back(name.c_str());
}
return archnames;
}
std::vector<const char *> SLAArchiveReader::get_extensions(const char *archtype)
{
auto it = REGISTERED_ARCHIVES.find(archtype);
if (it != REGISTERED_ARCHIVES.end())
return it->second.extensions;
return {};
}
const char *SLAArchiveReader::get_description(const char *archtype)
{
auto it = REGISTERED_ARCHIVES.find(archtype);
if (it != REGISTERED_ARCHIVES.end())
return it->second.descr;
return nullptr;
}
struct SliceParams { double layerh = 0., initial_layerh = 0.; };
static SliceParams get_slice_params(const DynamicPrintConfig &cfg)

View File

@ -47,15 +47,6 @@ public:
const std::string &format_id,
SLAImportQuality quality = SLAImportQuality::Balanced,
const ProgrFn &progr = [](int) { return false; });
// Get the names of currently known archive reader implementations
static const std::vector<const char *> & registered_archives();
// Get the understood file extensions belonging to an archive format
static std::vector<const char *> get_extensions(const char *archtype);
// Generic description (usable in GUI) about an archive format
static const char * get_description(const char *archtype);
};
// Raised in import_sla_archive when a nullptr reader is returned by

View File

@ -1,77 +1,18 @@
#include "SLAArchiveWriter.hpp"
#include "SL1.hpp"
#include "SL1_SVG.hpp"
#include "AnycubicSLA.hpp"
#include "libslic3r/libslic3r.h"
#include <string>
#include <map>
#include <memory>
#include <tuple>
#include "SLAArchiveFormatRegistry.hpp"
namespace Slic3r {
using ArchiveFactory = std::function<std::unique_ptr<SLAArchiveWriter>(const SLAPrinterConfig&)>;
struct ArchiveEntry {
const char *ext;
ArchiveFactory factoryfn;
};
static const std::map<std::string, ArchiveEntry> REGISTERED_ARCHIVES {
{
"SL1",
{ "sl1", [] (const auto &cfg) { return std::make_unique<SL1Archive>(cfg); } }
},
{
"SL1SVG",
{ "sl1_svg", [] (const auto &cfg) { return std::make_unique<SL1_SVGArchive>(cfg); } }
},
{
"SL2",
{ "sl1_svg", [] (const auto &cfg) { return std::make_unique<SL1_SVGArchive>(cfg); } }
},
ANYCUBIC_SLA_FORMAT("pwmo", "Photon Mono"),
ANYCUBIC_SLA_FORMAT("pwmx", "Photon Mono X"),
ANYCUBIC_SLA_FORMAT("pwms", "Photon Mono SE"),
};
std::unique_ptr<SLAArchiveWriter>
SLAArchiveWriter::create(const std::string &archtype, const SLAPrinterConfig &cfg)
{
auto entry = REGISTERED_ARCHIVES.find(archtype);
std::unique_ptr<SLAArchiveWriter> ret;
auto factory = get_writer_factory(archtype.c_str());
if (entry != REGISTERED_ARCHIVES.end())
return entry->second.factoryfn(cfg);
if (factory)
ret = factory(cfg);
return nullptr;
}
const std::vector<const char*>& SLAArchiveWriter::registered_archives()
{
static std::vector<const char*> archnames;
if (archnames.empty()) {
archnames.reserve(REGISTERED_ARCHIVES.size());
for (auto &[name, _] : REGISTERED_ARCHIVES)
archnames.emplace_back(name.c_str());
}
return archnames;
}
const char *SLAArchiveWriter::get_extension(const char *archtype)
{
constexpr const char* DEFAULT_EXT = "zip";
auto entry = REGISTERED_ARCHIVES.find(archtype);
if (entry != REGISTERED_ARCHIVES.end())
return entry->second.ext;
return DEFAULT_EXT;
return ret;
}
} // namespace Slic3r

View File

@ -53,12 +53,6 @@ public:
// Factory method to create an archiver instance
static std::unique_ptr<SLAArchiveWriter> create(
const std::string &archtype, const SLAPrinterConfig &);
// Get the names of currently known archiver implementations
static const std::vector<const char *> & registered_archives();
// Get the default file extension belonging to an archive format
static const char *get_extension(const char *archtype);
};
} // namespace Slic3r

View File

@ -11,6 +11,7 @@
#include "libslic3r/AppConfig.hpp"
#include "libslic3r/Format/SLAArchiveReader.hpp"
#include "libslic3r/Format/SLAArchiveFormatRegistry.hpp"
#include "slic3r/GUI/I18N.hpp"
@ -29,11 +30,16 @@ std::string get_readers_wildcard()
{
std::string ret;
for (const char *archtype : SLAArchiveReader::registered_archives()) {
ret += into_u8(_(SLAArchiveReader::get_description(archtype)));
auto registry = registered_sla_archives();
for (const ArchiveEntry &entry : registry) {
if (!entry.rdfactoryfn)
continue;
ret += into_u8(_(entry.desc));
ret += " (";
auto extensions = SLAArchiveReader::get_extensions(archtype);
for (const char * ext : extensions) {
std::vector<std::string> extensions = get_extensions(entry);
for (const std::string &ext : extensions) {
ret += "*.";
ret += ext;
ret += ", ";

View File

@ -3,6 +3,7 @@
#include "libslic3r/SLAPrint.hpp"
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/Format/SLAArchiveFormatRegistry.hpp"
#include "libslic3r/Format/SLAArchiveWriter.hpp"
#include "libslic3r/Format/SLAArchiveReader.hpp"
@ -11,16 +12,18 @@
using namespace Slic3r;
TEST_CASE("Archive export test", "[sla_archives]") {
auto registry = registered_sla_archives();
for (const char * pname : {"20mm_cube", "extruder_idler"})
for (auto &archname : SLAArchiveWriter::registered_archives()) {
INFO(std::string("Testing archive type: ") + archname + " -- writing...");
for (const ArchiveEntry &entry : registry) {
INFO(std::string("Testing archive type: ") + entry.id + " -- writing...");
SLAPrint print;
SLAFullPrintConfig fullcfg;
auto m = Model::read_from_file(TEST_DATA_DIR PATH_SEPARATOR + std::string(pname) + ".obj", nullptr);
fullcfg.printer_technology.setInt(ptSLA); // FIXME this should be ensured
fullcfg.set("sla_archive_format", archname);
fullcfg.set("sla_archive_format", entry.id);
fullcfg.set("supports_enable", false);
fullcfg.set("pad_enable", false);
@ -32,7 +35,7 @@ TEST_CASE("Archive export test", "[sla_archives]") {
print.process();
ThumbnailsList thumbnails;
auto outputfname = std::string("output_") + pname + "." + SLAArchiveWriter::get_extension(archname);
auto outputfname = std::string("output_") + pname + "." + entry.ext;
print.export_print(outputfname, thumbnails, pname);
@ -41,12 +44,8 @@ TEST_CASE("Archive export test", "[sla_archives]") {
double vol_written = m.mesh().volume();
auto readable_formats = SLAArchiveReader::registered_archives();
if (std::any_of(readable_formats.begin(), readable_formats.end(),
[&archname](const std::string &a) { return a == archname; })) {
INFO(std::string("Testing archive type: ") + archname + " -- reading back...");
if (entry.rdfactoryfn) {
INFO(std::string("Testing archive type: ") + entry.id + " -- reading back...");
indexed_triangle_set its;
DynamicPrintConfig cfg;