diff --git a/ACT/LibMCEnv.xml b/ACT/LibMCEnv.xml
index 8a34b06b..622bff8d 100644
--- a/ACT/LibMCEnv.xml
+++ b/ACT/LibMCEnv.xml
@@ -6419,6 +6419,12 @@
+
+
+
+
+
+
diff --git a/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.h b/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.h
index 4fc7cb6b..b8ac7e41 100644
--- a/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.h
+++ b/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.h
@@ -11868,6 +11868,19 @@ typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_GetBuildExecutionPtr) (LibMCEnv_
*/
typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_GetRecentBuildJobsPtr) (LibMCEnv_UIEnvironment pUIEnvironment, LibMCEnv_uint32 nMaxCount, LibMCEnv_BuildIterator * pBuildIterator);
+/**
+* Creates a new build job from an existing storage stream. The storage stream must contain a valid 3MF file.
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] pStorageStreamUUID - UUID of the storage stream containing the 3MF file.
+* @param[in] pBuildName - Display name for the build job. Must not be empty.
+* @param[in] nBuildUUIDBufferSize - size of the buffer (including trailing 0)
+* @param[out] pBuildUUIDNeededChars - will be filled with the count of the written bytes, or needed buffer size.
+* @param[out] pBuildUUIDBuffer - buffer of UUID of the newly created build job., may be NULL
+* @return error code or 0 (success)
+*/
+typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_CreateBuildJobFromStoragePtr) (LibMCEnv_UIEnvironment pUIEnvironment, const char * pStorageStreamUUID, const char * pBuildName, const LibMCEnv_uint32 nBuildUUIDBufferSize, LibMCEnv_uint32* pBuildUUIDNeededChars, char * pBuildUUIDBuffer);
+
/**
* Creates an empty discrete field.
*
@@ -13436,6 +13449,7 @@ typedef struct {
PLibMCEnvUIEnvironment_HasBuildExecutionPtr m_UIEnvironment_HasBuildExecution;
PLibMCEnvUIEnvironment_GetBuildExecutionPtr m_UIEnvironment_GetBuildExecution;
PLibMCEnvUIEnvironment_GetRecentBuildJobsPtr m_UIEnvironment_GetRecentBuildJobs;
+ PLibMCEnvUIEnvironment_CreateBuildJobFromStoragePtr m_UIEnvironment_CreateBuildJobFromStorage;
PLibMCEnvUIEnvironment_CreateDiscreteField2DPtr m_UIEnvironment_CreateDiscreteField2D;
PLibMCEnvUIEnvironment_CreateDiscreteField2DFromImagePtr m_UIEnvironment_CreateDiscreteField2DFromImage;
PLibMCEnvUIEnvironment_CheckPermissionPtr m_UIEnvironment_CheckPermission;
diff --git a/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.hpp b/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.hpp
index d6bd51f0..98398703 100644
--- a/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.hpp
+++ b/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.hpp
@@ -3819,6 +3819,7 @@ class CUIEnvironment : public CBase {
inline bool HasBuildExecution(const std::string & sExecutionUUID);
inline PBuildExecution GetBuildExecution(const std::string & sExecutionUUID);
inline PBuildIterator GetRecentBuildJobs(const LibMCEnv_uint32 nMaxCount);
+ inline std::string CreateBuildJobFromStorage(const std::string & sStorageStreamUUID, const std::string & sBuildName);
inline PDiscreteFieldData2D CreateDiscreteField2D(const LibMCEnv_uint32 nPixelCountX, const LibMCEnv_uint32 nPixelCountY, const LibMCEnv_double dDPIValueX, const LibMCEnv_double dDPIValueY, const LibMCEnv_double dOriginX, const LibMCEnv_double dOriginY, const LibMCEnv_double dDefaultValue);
inline PDiscreteFieldData2D CreateDiscreteField2DFromImage(classParam pImageDataInstance, const LibMCEnv_double dBlackValue, const LibMCEnv_double dWhiteValue, const LibMCEnv_double dOriginX, const LibMCEnv_double dOriginY);
inline bool CheckPermission(const std::string & sPermissionIdentifier);
@@ -5044,6 +5045,7 @@ class CUIEnvironment : public CBase {
pWrapperTable->m_UIEnvironment_HasBuildExecution = nullptr;
pWrapperTable->m_UIEnvironment_GetBuildExecution = nullptr;
pWrapperTable->m_UIEnvironment_GetRecentBuildJobs = nullptr;
+ pWrapperTable->m_UIEnvironment_CreateBuildJobFromStorage = nullptr;
pWrapperTable->m_UIEnvironment_CreateDiscreteField2D = nullptr;
pWrapperTable->m_UIEnvironment_CreateDiscreteField2DFromImage = nullptr;
pWrapperTable->m_UIEnvironment_CheckPermission = nullptr;
@@ -15065,6 +15067,15 @@ class CUIEnvironment : public CBase {
if (pWrapperTable->m_UIEnvironment_GetRecentBuildJobs == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+ #ifdef _WIN32
+ pWrapperTable->m_UIEnvironment_CreateBuildJobFromStorage = (PLibMCEnvUIEnvironment_CreateBuildJobFromStoragePtr) GetProcAddress(hLibrary, "libmcenv_uienvironment_createbuildjobfromstorage");
+ #else // _WIN32
+ pWrapperTable->m_UIEnvironment_CreateBuildJobFromStorage = (PLibMCEnvUIEnvironment_CreateBuildJobFromStoragePtr) dlsym(hLibrary, "libmcenv_uienvironment_createbuildjobfromstorage");
+ dlerror();
+ #endif // _WIN32
+ if (pWrapperTable->m_UIEnvironment_CreateBuildJobFromStorage == nullptr)
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
#ifdef _WIN32
pWrapperTable->m_UIEnvironment_CreateDiscreteField2D = (PLibMCEnvUIEnvironment_CreateDiscreteField2DPtr) GetProcAddress(hLibrary, "libmcenv_uienvironment_creatediscretefield2d");
#else // _WIN32
@@ -19889,6 +19900,10 @@ class CUIEnvironment : public CBase {
if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_GetRecentBuildJobs == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+ eLookupError = (*pLookup)("libmcenv_uienvironment_createbuildjobfromstorage", (void**)&(pWrapperTable->m_UIEnvironment_CreateBuildJobFromStorage));
+ if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_CreateBuildJobFromStorage == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
eLookupError = (*pLookup)("libmcenv_uienvironment_creatediscretefield2d", (void**)&(pWrapperTable->m_UIEnvironment_CreateDiscreteField2D));
if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_CreateDiscreteField2D == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
@@ -35363,6 +35378,23 @@ class CUIEnvironment : public CBase {
return std::make_shared(m_pWrapper, hBuildIterator);
}
+ /**
+ * CUIEnvironment::CreateBuildJobFromStorage - Creates a new build job from an existing storage stream. The storage stream must contain a valid 3MF file.
+ * @param[in] sStorageStreamUUID - UUID of the storage stream containing the 3MF file.
+ * @param[in] sBuildName - Display name for the build job. Must not be empty.
+ * @return UUID of the newly created build job.
+ */
+ std::string CUIEnvironment::CreateBuildJobFromStorage(const std::string & sStorageStreamUUID, const std::string & sBuildName)
+ {
+ LibMCEnv_uint32 bytesNeededBuildUUID = 0;
+ LibMCEnv_uint32 bytesWrittenBuildUUID = 0;
+ CheckError(m_pWrapper->m_WrapperTable.m_UIEnvironment_CreateBuildJobFromStorage(m_pHandle, sStorageStreamUUID.c_str(), sBuildName.c_str(), 0, &bytesNeededBuildUUID, nullptr));
+ std::vector bufferBuildUUID(bytesNeededBuildUUID);
+ CheckError(m_pWrapper->m_WrapperTable.m_UIEnvironment_CreateBuildJobFromStorage(m_pHandle, sStorageStreamUUID.c_str(), sBuildName.c_str(), bytesNeededBuildUUID, &bytesWrittenBuildUUID, &bufferBuildUUID[0]));
+
+ return std::string(&bufferBuildUUID[0]);
+ }
+
/**
* CUIEnvironment::CreateDiscreteField2D - Creates an empty discrete field.
* @param[in] nPixelCountX - Pixel count in X. MUST be positive.
diff --git a/Framework/InterfacesCore/libmcenv_abi.hpp b/Framework/InterfacesCore/libmcenv_abi.hpp
index fc711aa4..a0853131 100644
--- a/Framework/InterfacesCore/libmcenv_abi.hpp
+++ b/Framework/InterfacesCore/libmcenv_abi.hpp
@@ -11881,6 +11881,19 @@ LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_getbuildexecution(LibMCE
*/
LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_getrecentbuildjobs(LibMCEnv_UIEnvironment pUIEnvironment, LibMCEnv_uint32 nMaxCount, LibMCEnv_BuildIterator * pBuildIterator);
+/**
+* Creates a new build job from an existing storage stream. The storage stream must contain a valid 3MF file.
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] pStorageStreamUUID - UUID of the storage stream containing the 3MF file.
+* @param[in] pBuildName - Display name for the build job. Must not be empty.
+* @param[in] nBuildUUIDBufferSize - size of the buffer (including trailing 0)
+* @param[out] pBuildUUIDNeededChars - will be filled with the count of the written bytes, or needed buffer size.
+* @param[out] pBuildUUIDBuffer - buffer of UUID of the newly created build job., may be NULL
+* @return error code or 0 (success)
+*/
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_createbuildjobfromstorage(LibMCEnv_UIEnvironment pUIEnvironment, const char * pStorageStreamUUID, const char * pBuildName, const LibMCEnv_uint32 nBuildUUIDBufferSize, LibMCEnv_uint32* pBuildUUIDNeededChars, char * pBuildUUIDBuffer);
+
/**
* Creates an empty discrete field.
*
diff --git a/Framework/InterfacesCore/libmcenv_interfaces.hpp b/Framework/InterfacesCore/libmcenv_interfaces.hpp
index 7a068575..072aca16 100644
--- a/Framework/InterfacesCore/libmcenv_interfaces.hpp
+++ b/Framework/InterfacesCore/libmcenv_interfaces.hpp
@@ -9062,6 +9062,14 @@ class IUIEnvironment : public virtual IBase {
*/
virtual IBuildIterator * GetRecentBuildJobs(const LibMCEnv_uint32 nMaxCount) = 0;
+ /**
+ * IUIEnvironment::CreateBuildJobFromStorage - Creates a new build job from an existing storage stream. The storage stream must contain a valid 3MF file.
+ * @param[in] sStorageStreamUUID - UUID of the storage stream containing the 3MF file.
+ * @param[in] sBuildName - Display name for the build job. Must not be empty.
+ * @return UUID of the newly created build job.
+ */
+ virtual std::string CreateBuildJobFromStorage(const std::string & sStorageStreamUUID, const std::string & sBuildName) = 0;
+
/**
* IUIEnvironment::CreateDiscreteField2D - Creates an empty discrete field.
* @param[in] nPixelCountX - Pixel count in X. MUST be positive.
diff --git a/Framework/InterfacesCore/libmcenv_interfacewrapper.cpp b/Framework/InterfacesCore/libmcenv_interfacewrapper.cpp
index c276033c..6813b89b 100644
--- a/Framework/InterfacesCore/libmcenv_interfacewrapper.cpp
+++ b/Framework/InterfacesCore/libmcenv_interfacewrapper.cpp
@@ -35920,6 +35920,60 @@ LibMCEnvResult libmcenv_uienvironment_getrecentbuildjobs(LibMCEnv_UIEnvironment
}
}
+LibMCEnvResult libmcenv_uienvironment_createbuildjobfromstorage(LibMCEnv_UIEnvironment pUIEnvironment, const char * pStorageStreamUUID, const char * pBuildName, const LibMCEnv_uint32 nBuildUUIDBufferSize, LibMCEnv_uint32* pBuildUUIDNeededChars, char * pBuildUUIDBuffer)
+{
+ IBase* pIBaseClass = (IBase *)pUIEnvironment;
+
+ try {
+ if (pStorageStreamUUID == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ if (pBuildName == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ if ( (!pBuildUUIDBuffer) && !(pBuildUUIDNeededChars) )
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sStorageStreamUUID(pStorageStreamUUID);
+ std::string sBuildName(pBuildName);
+ std::string sBuildUUID("");
+ IUIEnvironment* pIUIEnvironment = dynamic_cast(pIBaseClass);
+ if (!pIUIEnvironment)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ bool isCacheCall = (pBuildUUIDBuffer == nullptr);
+ if (isCacheCall) {
+ sBuildUUID = pIUIEnvironment->CreateBuildJobFromStorage(sStorageStreamUUID, sBuildName);
+
+ pIUIEnvironment->_setCache (new ParameterCache_1 (sBuildUUID));
+ }
+ else {
+ auto cache = dynamic_cast*> (pIUIEnvironment->_getCache ());
+ if (cache == nullptr)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+ cache->retrieveData (sBuildUUID);
+ pIUIEnvironment->_setCache (nullptr);
+ }
+
+ if (pBuildUUIDNeededChars)
+ *pBuildUUIDNeededChars = (LibMCEnv_uint32) (sBuildUUID.size()+1);
+ if (pBuildUUIDBuffer) {
+ if (sBuildUUID.size() >= nBuildUUIDBufferSize)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_BUFFERTOOSMALL);
+ for (size_t iBuildUUID = 0; iBuildUUID < sBuildUUID.size(); iBuildUUID++)
+ pBuildUUIDBuffer[iBuildUUID] = sBuildUUID[iBuildUUID];
+ pBuildUUIDBuffer[sBuildUUID.size()] = 0;
+ }
+ return LIBMCENV_SUCCESS;
+ }
+ catch (ELibMCEnvInterfaceException & Exception) {
+ return handleLibMCEnvException(pIBaseClass, Exception);
+ }
+ catch (std::exception & StdException) {
+ return handleStdException(pIBaseClass, StdException);
+ }
+ catch (...) {
+ return handleUnhandledException(pIBaseClass);
+ }
+}
+
LibMCEnvResult libmcenv_uienvironment_creatediscretefield2d(LibMCEnv_UIEnvironment pUIEnvironment, LibMCEnv_uint32 nPixelCountX, LibMCEnv_uint32 nPixelCountY, LibMCEnv_double dDPIValueX, LibMCEnv_double dDPIValueY, LibMCEnv_double dOriginX, LibMCEnv_double dOriginY, LibMCEnv_double dDefaultValue, LibMCEnv_DiscreteFieldData2D * pFieldDataInstance)
{
IBase* pIBaseClass = (IBase *)pUIEnvironment;
@@ -39392,6 +39446,8 @@ LibMCEnvResult LibMCEnv::Impl::LibMCEnv_GetProcAddress (const char * pProcName,
*ppProcAddress = (void*) &libmcenv_uienvironment_getbuildexecution;
if (sProcName == "libmcenv_uienvironment_getrecentbuildjobs")
*ppProcAddress = (void*) &libmcenv_uienvironment_getrecentbuildjobs;
+ if (sProcName == "libmcenv_uienvironment_createbuildjobfromstorage")
+ *ppProcAddress = (void*) &libmcenv_uienvironment_createbuildjobfromstorage;
if (sProcName == "libmcenv_uienvironment_creatediscretefield2d")
*ppProcAddress = (void*) &libmcenv_uienvironment_creatediscretefield2d;
if (sProcName == "libmcenv_uienvironment_creatediscretefield2dfromimage")
diff --git a/Implementation/LibMCEnv/libmcenv_uienvironment.cpp b/Implementation/LibMCEnv/libmcenv_uienvironment.cpp
index 67e45b03..67b5915a 100644
--- a/Implementation/LibMCEnv/libmcenv_uienvironment.cpp
+++ b/Implementation/LibMCEnv/libmcenv_uienvironment.cpp
@@ -849,6 +849,96 @@ IBuildIterator* CUIEnvironment::GetRecentBuildJobs(const LibMCEnv_uint32 nMaxCou
return pResultIterator.release();
}
+std::string CUIEnvironment::CreateBuildJobFromStorage(const std::string& sStorageStreamUUID, const std::string& sBuildName)
+{
+ // Validate inputs
+ std::string sNormalizedStorageUUID = AMCCommon::CUtils::normalizeUUIDString(sStorageStreamUUID);
+
+ if (sBuildName.empty())
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDPARAM, "build name must not be empty");
+
+ // Get services
+ auto pDataModel = m_pUISystemState->getDataModel();
+ auto pStorage = pDataModel->CreateStorage();
+ auto pGlobalChrono = m_pUISystemState->getGlobalChronoInstance();
+
+ // Verify stream exists and is 3MF
+ if (!pStorage->StreamIsReady(sNormalizedStorageUUID))
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDPARAM, "storage stream does not exist: " + sNormalizedStorageUUID);
+
+ auto pStream = pStorage->RetrieveStream(sNormalizedStorageUUID);
+ if (pStream->GetMIMEType() != "application/3mf")
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDPARAM, "storage stream is not a 3MF file (MIME type: " + pStream->GetMIMEType() + ")");
+
+ // Create build job
+ std::string sBuildUUID = AMCCommon::CUtils::createUUID();
+ auto pBuildJobHandler = pDataModel->CreateBuildJobHandler();
+ pBuildJobHandler->CreateJob(
+ sBuildUUID,
+ sBuildName,
+ m_pAPIAuth->getUserUUID(),
+ sNormalizedStorageUUID,
+ pGlobalChrono->getUTCTimeStampInMicrosecondsSince1970()
+ );
+
+ // Validate and extract metadata
+ auto pBuildJob = pBuildJobHandler->RetrieveJob(sBuildUUID);
+ auto pToolpathHandler = m_pUISystemState->getToolpathHandler();
+
+ pBuildJob->StartValidating();
+
+ std::set attachmentRelationsToRead;
+ AMC::CToolpathEntity toolpathEntity(
+ pDataModel,
+ sNormalizedStorageUUID,
+ pToolpathHandler->getLib3MFWrapper(),
+ sBuildName,
+ true,
+ attachmentRelationsToRead
+ );
+
+ pBuildJob->FinishValidating(toolpathEntity.getLayerCount());
+
+ // Add toolpath data
+ pBuildJob->AddJobData(
+ pStream->GetContextIdentifier(),
+ pStream->GetName(),
+ pStream,
+ LibMCData::eCustomDataType::Toolpath,
+ m_pAPIAuth->getUserUUID(),
+ pGlobalChrono->getUTCTimeStampInMicrosecondsSince1970()
+ );
+
+ // Extract and add thumbnail if present
+ std::vector thumbNailBuffer;
+ std::string thumbNailMimeType;
+ if (toolpathEntity.readThumbnail(thumbNailBuffer, thumbNailMimeType)) {
+ std::string sThumbnailUUID = AMCCommon::CUtils::createUUID();
+ pStorage->StoreNewStream(
+ sThumbnailUUID,
+ "thumbnail",
+ thumbNailMimeType,
+ thumbNailBuffer,
+ m_pAPIAuth->getUserUUID(),
+ pGlobalChrono->getUTCTimeStampInMicrosecondsSince1970()
+ );
+ auto pThumbnailStream = pStorage->RetrieveStream(sThumbnailUUID);
+
+ pBuildJob->AddJobData(
+ "thumbnail",
+ "thumbnail",
+ pThumbnailStream,
+ LibMCData::eCustomDataType::Thumbnail,
+ m_pAPIAuth->getUserUUID(),
+ pGlobalChrono->getUTCTimeStampInMicrosecondsSince1970()
+ );
+
+ pBuildJob->SetThumbnailStreamUUID(sThumbnailUUID);
+ }
+
+ return sBuildUUID;
+}
+
IDiscreteFieldData2D* CUIEnvironment::CreateDiscreteField2D(const LibMCEnv_uint32 nPixelSizeX, const LibMCEnv_uint32 nPixelSizeY, const LibMCEnv_double dDPIValueX, const LibMCEnv_double dDPIValueY, const LibMCEnv_double dOriginX, const LibMCEnv_double dOriginY, const LibMCEnv_double dDefaultValue)
{
diff --git a/Implementation/LibMCEnv/libmcenv_uienvironment.hpp b/Implementation/LibMCEnv/libmcenv_uienvironment.hpp
index 42218821..f2aed315 100644
--- a/Implementation/LibMCEnv/libmcenv_uienvironment.hpp
+++ b/Implementation/LibMCEnv/libmcenv_uienvironment.hpp
@@ -238,6 +238,8 @@ class CUIEnvironment : public virtual IUIEnvironment, public virtual CBase {
IBuildIterator* GetRecentBuildJobs(const LibMCEnv_uint32 nMaxCount) override;
+ std::string CreateBuildJobFromStorage(const std::string& sStorageStreamUUID, const std::string& sBuildName) override;
+
IDiscreteFieldData2D* CreateDiscreteField2D(const LibMCEnv_uint32 nPixelSizeX, const LibMCEnv_uint32 nPixelSizeY, const LibMCEnv_double dDPIValueX, const LibMCEnv_double dDPIValueY, const LibMCEnv_double dOriginX, const LibMCEnv_double dOriginY, const LibMCEnv_double dDefaultValue) override;
IDiscreteFieldData2D* CreateDiscreteField2DFromImage(IImageData* pImageDataInstance, const LibMCEnv_double dBlackValue, const LibMCEnv_double dWhiteValue, const LibMCEnv_double dOriginX, const LibMCEnv_double dOriginY) override;