665 lines
27 KiB
C++
665 lines
27 KiB
C++
/***********************************************************************************************************************
|
|
*
|
|
* Copyright (c) 2010 - 2022 by Tech Soft 3D, Inc.
|
|
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
|
|
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
|
|
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
|
|
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
|
|
* scope and manner of such use.
|
|
*
|
|
***********************************************************************************************************************/
|
|
/**
|
|
\file DemoFunctionalities.cpp
|
|
|
|
This file demonstrates numerous functionalities of HOOPS Publish Advanced.
|
|
|
|
***********************************************************************************************************************/
|
|
|
|
#define INITIALIZE_A3D_API
|
|
#define HOOPS_PRODUCT_PUBLISH_ADVANCED
|
|
#include <A3DSDKIncludes.h>
|
|
#include "../common.hpp"
|
|
#include "../CommonInit.h"
|
|
|
|
#include <sstream>
|
|
#include <ostream>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
|
|
// default sample arguments:
|
|
// in visual c++: the current directory is set through properties to $OutDir, which is $(Platform)\$(Configuration)
|
|
// in linux: the current directory is supposed to be the same as this cpp file
|
|
#ifdef _MSC_VER
|
|
# define IN_3DFILE SAMPLES_DATA_DIRECTORY"\\prc\\Crank-Instructions.prc"
|
|
# define OUT_FILE SAMPLES_PUBLISH_GALLERY_DIRECTORY"\\sample_DemoFunctionalitiesAdv.pdf"
|
|
# define POSTER_PATH SAMPLES_DATA_DIRECTORY"\\images\\pleaseactivate.bmp"
|
|
# define ICON_PATH SAMPLES_DATA_DIRECTORY"\\images\\"
|
|
# define IN_LOGO SAMPLES_DATA_DIRECTORY"\\images\\logo_e.jpg"
|
|
# define PDF_TEMPLATE SAMPLES_DATA_DIRECTORY"\\pdf_templates\\DemoFuncTemplate.pdf"
|
|
#else
|
|
# define IN_3DFILE SAMPLES_DATA_DIRECTORY"/prc/Crank-Instructions.prc"
|
|
# define OUT_FILE SAMPLES_PUBLISH_GALLERY_DIRECTORY"/sample_DemoFunctionalitiesAdv.pdf"
|
|
# define POSTER_PATH SAMPLES_DATA_DIRECTORY"/images/pleaseactivate.bmp"
|
|
# define ICON_PATH SAMPLES_DATA_DIRECTORY"/images/"
|
|
# define IN_LOGO SAMPLES_DATA_DIRECTORY"/images/logo_e.jpg"
|
|
# define PDF_TEMPLATE SAMPLES_DATA_DIRECTORY"/pdf_templates/DemoFuncTemplate.pdf"
|
|
#endif
|
|
|
|
// rgb colors
|
|
#define COL_BLACK 0.0, 0.0, 0.0
|
|
#define COL_RED 1.0, 0.0, 0.0
|
|
#define COL_LIGHTGREY 0.4, 0.4, 0.4
|
|
|
|
const size_t MAXSZFILENAME = 4096;
|
|
|
|
|
|
|
|
std::string intToString(int i)
|
|
{
|
|
std::ostringstream oss;
|
|
oss << i;
|
|
return oss.str();
|
|
}
|
|
|
|
//######################################################################################################################
|
|
|
|
static bool string_equals(A3DUTF8Char* pcString1, const std::string& sString2)
|
|
{
|
|
std::string sStringCmp1 = pcString1 ? pcString1 : "";
|
|
std::string sStringCmp2 = sString2;
|
|
|
|
return (sStringCmp1 == sStringCmp2);
|
|
}
|
|
|
|
|
|
//######################################################################################################################
|
|
A3DStatus Create3DAnnot(A3DPDFDocument* pDoc,
|
|
const A3DUTF8Char* pcFileName,
|
|
A3DPDFImage* pPoster,
|
|
const A3DUTF8Char* pcInjsfile,
|
|
A3DPDF3DArtwork** pp3DArtwork,
|
|
A3DPDF3DAnnot** pp3DAnnot,
|
|
A3DRWParamsPrcWriteHelper** ppA3DRWParamsPrcWriteHelper,
|
|
A3DAsmModelFile** ppModelFile)
|
|
{
|
|
A3DStatus iRet = A3D_SUCCESS;
|
|
*pp3DAnnot = NULL;
|
|
*ppModelFile = NULL;
|
|
A3DPDF3DStream* pStream = NULL;
|
|
char tempfilename[1024];
|
|
|
|
// Publish 6.0 - Particularity when the input 3D model is stored in a PDF file. The functions to read the 3D data from the PDF
|
|
// are not the same as for other formats.
|
|
if (strstr(pcFileName, ".pdf") != NULL)
|
|
{
|
|
A3DStream3DPDFData* pStream3DPDFData;
|
|
A3DInt32 iNumStreams;
|
|
iRet = A3DGet3DPDFStreams(pcFileName, &pStream3DPDFData, &iNumStreams);
|
|
if (iRet != A3D_SUCCESS || iNumStreams == 0)
|
|
return A3D_ERROR;
|
|
|
|
// a real use case might parse every streams in the input file. Here we just take the first one (pStream3DPDFData[0]).
|
|
|
|
// even an input PRC file must be read in memory and mapped into modelfile data structures
|
|
if (pStream3DPDFData[0].m_bIsPrc)
|
|
{
|
|
iRet = A3DAsmModelFileLoadFromPrcStream(pStream3DPDFData[0].m_acStream, pStream3DPDFData[0].m_uiStreamSize, NULL, ppModelFile);
|
|
if (iRet != A3D_SUCCESS)
|
|
{
|
|
A3DGet3DPDFStreams(NULL, &pStream3DPDFData, &iNumStreams); // to clean up the array of stream data
|
|
return iRet;
|
|
}
|
|
}
|
|
// a U3D stream must first be stored as a physical file ; then 2 situations occur:
|
|
// 1. read and LOAD the physical file into a modelfile using the common A3DAsmModelFileLoadFromFile function, then transform the modelfile into a stream
|
|
// OR
|
|
// 2. read the physical file into a binary stream (not loaded into a modelfile) using A3DPDF3DStreamCreateFromFile function
|
|
// In this sample we illustrate the workflow 2.
|
|
else
|
|
{
|
|
sprintf(tempfilename, "%s.u3d", OUT_FILE);
|
|
FILE * pFile = NULL;
|
|
#ifdef _MSC_VER
|
|
errno_t ret = fopen_s(&pFile, tempfilename, "wb");
|
|
if (ret == 0 && pFile)
|
|
#else
|
|
pFile = fopen(tempfilename, "wb");
|
|
if (pFile)
|
|
#endif
|
|
{
|
|
fwrite(pStream3DPDFData[0].m_acStream, 1, pStream3DPDFData[0].m_uiStreamSize, pFile);
|
|
fclose(pFile);
|
|
}
|
|
|
|
// physical file to stream
|
|
CHECK_RET(A3DPDF3DStreamCreateFromFile(pDoc, tempfilename, false, &pStream));
|
|
|
|
// !!! the file will have to be disposed of afterwards
|
|
remove(tempfilename);
|
|
}
|
|
|
|
A3DGet3DPDFStreams(NULL, &pStream3DPDFData, &iNumStreams); // to clean up the array of stream data
|
|
}
|
|
|
|
// Load the physical file in a ModelFile data structure if not already done
|
|
if (pStream == NULL && *ppModelFile == NULL)
|
|
{
|
|
// reading the input CAD file; the file can be disposed of afterwards.
|
|
A3DRWParamsLoadData sReadParam;
|
|
A3D_INITIALIZE_DATA(A3DRWParamsLoadData, sReadParam);
|
|
|
|
sReadParam.m_sGeneral.m_bReadSolids = true;
|
|
sReadParam.m_sGeneral.m_bReadSurfaces = true;
|
|
sReadParam.m_sGeneral.m_bReadWireframes = true;
|
|
sReadParam.m_sGeneral.m_bReadPmis = true;
|
|
sReadParam.m_sGeneral.m_bReadAttributes = true;
|
|
sReadParam.m_sGeneral.m_bReadHiddenObjects = false;
|
|
sReadParam.m_sGeneral.m_bReadConstructionAndReferences = false;
|
|
sReadParam.m_sGeneral.m_bReadActiveFilter = true;
|
|
sReadParam.m_sGeneral.m_eReadingMode2D3D = kA3DRead_3D;
|
|
sReadParam.m_sGeneral.m_eReadGeomTessMode = kA3DReadGeomAndTess;
|
|
sReadParam.m_sGeneral.m_eDefaultUnit = kA3DUnitUnknown;
|
|
sReadParam.m_sPmi.m_bAlwaysSubstituteFont = false;
|
|
sReadParam.m_sPmi.m_pcSubstitutionFont = const_cast<A3DUTF8Char*>("Myriad CAD");
|
|
sReadParam.m_sTessellation.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
|
|
sReadParam.m_sMultiEntries.m_bLoadDefault = true;
|
|
sReadParam.m_sAssembly.m_bUseRootDirectory = true;
|
|
CHECK_RET(A3DAsmModelFileLoadFromFile(pcFileName, &sReadParam, ppModelFile));
|
|
}
|
|
|
|
if (*ppModelFile != NULL)
|
|
{
|
|
// whatever the input format, we store it as PRC in the output PDF
|
|
// creating the PRC stream from the model file that is going to be inserted into the PDF file
|
|
A3DRWParamsExportPrcData sParamsExportData;
|
|
A3D_INITIALIZE_DATA(A3DRWParamsExportPrcData, sParamsExportData);
|
|
|
|
// To get unique IDs, we need a A3DRWParamsPrcWriteHelper.
|
|
// A3DPDF3DStreamCreateFromModelFileAsPRC builds this object.
|
|
CHECK_RET(A3DPDF3DStreamCreateFromModelFileAsPRC(pDoc, *ppModelFile, &sParamsExportData, &pStream, ppA3DRWParamsPrcWriteHelper));
|
|
}
|
|
|
|
if (pStream != NULL)
|
|
{
|
|
// creating the 3D artwork
|
|
*pp3DArtwork = NULL;
|
|
A3DPDF3DArtworkData2 s3DArtworkData;
|
|
A3D_INITIALIZE_DATA(A3DPDF3DArtworkData2, s3DArtworkData);
|
|
|
|
s3DArtworkData.m_pStream = pStream;
|
|
s3DArtworkData.m_pcJavaScriptFileName = const_cast<A3DUTF8Char*>(pcInjsfile);
|
|
s3DArtworkData.m_sDisplaySectionData.m_bAddSectionCaps = true;
|
|
CHECK_RET(A3DPDF3DArtworkCreate2(pDoc, &s3DArtworkData, pp3DArtwork));
|
|
|
|
A3DPDF3DAnnotData sAnnotData;
|
|
A3D_INITIALIZE_DATA(A3DPDF3DAnnotData, sAnnotData);
|
|
|
|
sAnnotData.m_bOpenModelTree = false;
|
|
sAnnotData.m_bShowToolbar = false;
|
|
sAnnotData.m_eLighting = kA3DPDFLightCADOptimized;
|
|
sAnnotData.m_eRenderingStyle = kA3DPDFRenderingSolid;
|
|
sAnnotData.m_sBackgroundColor.m_dRed = 0.25;
|
|
sAnnotData.m_sBackgroundColor.m_dGreen = 0.25;
|
|
sAnnotData.m_sBackgroundColor.m_dBlue = 0.25;
|
|
sAnnotData.m_bTransparentBackground = false;
|
|
sAnnotData.m_eActivateWhen = kA3DPDFActivPageOpened;
|
|
sAnnotData.m_eDesactivateWhen = kA3DPDFActivPageClosed;
|
|
sAnnotData.m_iAppearanceBorderWidth = 0;
|
|
sAnnotData.m_pPosterImage = pPoster; // default poster automatically generated
|
|
sAnnotData.m_p3DArtwork = *pp3DArtwork;
|
|
|
|
CHECK_RET(A3DPDF3DAnnotCreate(pDoc, &sAnnotData, pp3DAnnot));
|
|
|
|
// cleaning up -- WARNING: DO NOT CALL THIS BEFORE inserting the 3D annot
|
|
//CHECK_RET(A3DAsmModelFileDelete(pModelFile));
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
|
|
|
|
|
|
//######################################################################################################################
|
|
// a usage scenario could be that the application user selects the fields to populate on the page.
|
|
// we simulate this with booleans.
|
|
static A3DStatus stPopulateDFTemplate(A3DPDFDocument* pDoc,
|
|
A3DPDFPage* pPage,
|
|
A3DPDF3DArtwork* p3DArtwork,
|
|
A3DPDF3DAnnot* p3DAnnot,
|
|
const std::string& sSuffixFields,
|
|
bool bFieldTitle, const A3DUTF8Char* pcTitle,
|
|
bool bFieldDate, const A3DUTF8Char* pcDate,
|
|
bool bFieldViews,
|
|
bool bFieldParts,
|
|
const std::vector<std::vector<std::string> >& aTable3DRows)
|
|
{
|
|
A3DStatus iRet = A3D_SUCCESS;
|
|
|
|
if (p3DAnnot != NULL)
|
|
{
|
|
// with A3DPDFDocumentAppendPageFromPDFFileAndSuffixFields:
|
|
// if template imported providing pcAppendStringToFieldNames, the field name is FieldName_pcAppendStringToFieldNames
|
|
|
|
A3DInt32 iNbFields;
|
|
A3DPDFField** ppFields;
|
|
CHECK_RET(A3DPDFPageGetFields(pPage, &iNbFields, &ppFields));
|
|
|
|
// parsing the fields to get the information.
|
|
for (A3DInt32 ifield = 0; ifield < iNbFields; ++ifield)
|
|
{
|
|
A3DPDFFieldData sFieldData;
|
|
A3D_INITIALIZE_DATA(A3DPDFFieldData, sFieldData);
|
|
CHECK_RET(A3DPDFFieldGetInformation(ppFields[ifield], &sFieldData));
|
|
|
|
if (string_equals(sFieldData.m_acName, "DF_Title_" + sSuffixFields) && bFieldTitle)
|
|
{
|
|
CHECK_RET(A3DPDFPageFieldTextSetValue(pPage, sFieldData.m_acName, pcTitle));
|
|
}
|
|
else if (string_equals(sFieldData.m_acName, "DF_Date_" + sSuffixFields) && bFieldDate)
|
|
{
|
|
CHECK_RET(A3DPDFPageFieldTextSetValue(pPage, sFieldData.m_acName, pcDate));
|
|
}
|
|
else if (string_equals(sFieldData.m_acName, "DF_3DWindow_" + sSuffixFields)) // always 3D
|
|
{
|
|
// populating the field with the 3D annotation
|
|
CHECK_RET(A3DPDFPageFieldSet3DAnnot(pPage, sFieldData.m_acName, p3DAnnot));
|
|
}
|
|
else if (string_equals(sFieldData.m_acName, "DF_ViewsList_" + sSuffixFields) && bFieldViews)
|
|
{
|
|
// get the view names from the 3D model
|
|
// getting view IDs as stored in the original file
|
|
A3DUns32 uiNbViews;
|
|
A3DPDFView** ppViews;
|
|
CHECK_RET(A3DPDF3DArtworkGetViews(p3DArtwork, &uiNbViews, &ppViews));
|
|
|
|
// parsing the views to get the identifier.
|
|
for (A3DUns32 ui = 0; ui < uiNbViews; ++ui)
|
|
{
|
|
A3DUTF8Char* pcViewId = NULL;
|
|
A3DPDFViewGetExternalName(ppViews[ui], &pcViewId);
|
|
|
|
CHECK_RET(A3DPDFPageFieldListAddItem(pPage, sFieldData.m_acName, pcViewId, pcViewId));
|
|
|
|
A3DPDFViewGetExternalName(nullptr,&pcViewId);
|
|
}
|
|
iRet = A3DPDF3DArtworkGetViews(NULL, NULL, &ppViews); // clean
|
|
|
|
// For a dropdown list (combo box), the JavaScript should be set on KeyStroke event with event.willCommit filtered,
|
|
// and it should use event.value to get the selected item value.
|
|
// Note that only the item value can be retrieved from the JavaScript, the export value is not enabled here.
|
|
std::ostringstream osJsOnField;
|
|
osJsOnField << "if( event.willCommit )\n";
|
|
osJsOnField << "{\n";
|
|
osJsOnField << " if(!event.value == \"\")\n";
|
|
osJsOnField << " {\n";
|
|
osJsOnField << " // activate view on related 3d annot (3d annot is supposed on the same page as the field)\n";
|
|
osJsOnField << " annot3d_related = this.getAnnots3D(event.target.page)[0];\n";
|
|
osJsOnField << " textfield_viewselected = this.getField(\"DF_ViewSelected_" << sSuffixFields << "\");\n";
|
|
osJsOnField << " textfield_viewselected.value = event.value;\n";
|
|
osJsOnField << " activateview(annot3d_related, textfield_viewselected.value);\n";
|
|
osJsOnField << " }\n";
|
|
osJsOnField << "}";
|
|
|
|
// For a dropdown list (combo box), the JavaScript should be set on KeyStroke event to be able to get the selected item.
|
|
CHECK_RET(A3DPDFPageFieldSetActionJavascript(pPage, sFieldData.m_acName, kA3DPDFEventFieldKeyStroke, osJsOnField.str().c_str()));
|
|
// also, the dropdown list must be set at commitOnSelChange true so that selection works fine
|
|
// modify the field at document opening
|
|
std::ostringstream osJsOnDoc;
|
|
osJsOnDoc << "// table definition for dropdown object " << sFieldData.m_acName << "\n";
|
|
osJsOnDoc << "var lstObj_" << sFieldData.m_acName << " = this.getField(\"" << sFieldData.m_acName << "\");\n";
|
|
osJsOnDoc << "lstObj_" << sFieldData.m_acName << ".commitOnSelChange = true;\n";
|
|
osJsOnDoc << "\n";
|
|
CHECK_RET(A3DPDFDocumentAddJavascriptFromString(pDoc, "DF_ViewsList_Fns", osJsOnDoc.str().c_str()));
|
|
|
|
}
|
|
else if (string_equals(sFieldData.m_acName, "DF_ViewsTitle_" + sSuffixFields) && bFieldViews)
|
|
{
|
|
CHECK_RET(A3DPDFPageFieldSetVisibility(pPage, sFieldData.m_acName, true));
|
|
}
|
|
else if (string_equals(sFieldData.m_acName, "DF_ViewSelectedTitle_" + sSuffixFields) && bFieldViews)
|
|
{
|
|
CHECK_RET(A3DPDFPageFieldSetVisibility(pPage, sFieldData.m_acName, true));
|
|
}
|
|
else if (string_equals(sFieldData.m_acName, "DF_ViewSelected_" + sSuffixFields) && bFieldViews)
|
|
{
|
|
CHECK_RET(A3DPDFPageFieldSetVisibility(pPage, sFieldData.m_acName, true));
|
|
}
|
|
else if (string_equals(sFieldData.m_acName, "DF_PartsList_" + sSuffixFields) && bFieldParts)
|
|
{
|
|
// Setting data and behaviour on listbox field:
|
|
// To avoid an issue with poorly selectable scroller in Acrobat, we need to
|
|
// * be sure the field has multipleSelection and commitOnSelChange options set to false
|
|
// * set the javascript on Keystroke event,
|
|
// * get selected value with 'event.changeEx' (which is the export value)
|
|
// * maintain a separated list to get additional data.
|
|
|
|
std::ostringstream osListItems;
|
|
|
|
// adding the items in listbox + separate list data
|
|
for (size_t i = 0; i < aTable3DRows.size(); ++i)
|
|
{
|
|
std::string sIdxItem = intToString((int)i);
|
|
|
|
// store the icon corresponding to the part
|
|
std::string sIconfile = std::string(ICON_PATH) + aTable3DRows[i][2].c_str();
|
|
std::string sIconname = "icon" + sIdxItem;
|
|
A3DPDFImage* pImage;
|
|
iRet = A3DPDFImageCreateFromFile(pDoc, sIconfile.c_str(), kA3DPDFImageFormatUnknown, &pImage);
|
|
if (iRet == A3D_SUCCESS)
|
|
{
|
|
// here we want to force the iconid as we use the index to name it later in javascript
|
|
CHECK_RET(A3DPDFDocumentAddImageAsIcon2(pDoc, pImage, sIconname.c_str(), NULL));
|
|
}
|
|
|
|
// .data = [nodeuid, icon]
|
|
osListItems << "lstObj_" << sFieldData.m_acName << ".data[" << i << "] = [ \"" << aTable3DRows[i][1].c_str() << "\", \"" << sIconname.c_str() << "\" ];\n";
|
|
|
|
// list item (visible value/export value) in droplist is: nodename / idx_in_listItemsTable
|
|
CHECK_RET(A3DPDFPageFieldListAddItem(pPage, sFieldData.m_acName, aTable3DRows[i][0].c_str(), sIdxItem.c_str()));
|
|
}
|
|
|
|
// modify the field at document opening to be sure selection works with slider + store list data
|
|
std::ostringstream osJsOnDoc;
|
|
osJsOnDoc << "// table definition for listbox object " << sFieldData.m_acName << "\n";
|
|
osJsOnDoc << "var lstObj_" << sFieldData.m_acName << " = this.getField(\"" << sFieldData.m_acName << "\");\n";
|
|
osJsOnDoc << "lstObj_" << sFieldData.m_acName << ".data = new Array();\n";
|
|
osJsOnDoc << osListItems.str();
|
|
osJsOnDoc << "lstObj_" << sFieldData.m_acName << ".multipleSelection = false;\n";
|
|
osJsOnDoc << "lstObj_" << sFieldData.m_acName << ".commitOnSelChange = false;\n";
|
|
osJsOnDoc << "\n";
|
|
CHECK_RET(A3DPDFDocumentAddJavascriptFromString(pDoc, "DF_PartsList_Fns", osJsOnDoc.str().c_str()));
|
|
|
|
// set an action to populate a text field and an icon from the selected item in the list
|
|
std::ostringstream osJsOnField;
|
|
osJsOnField << "thisfield = event.target;\n";
|
|
osJsOnField << "if (event.changeEx!=\"\")\n";
|
|
osJsOnField << "{\n";
|
|
osJsOnField << " var idx = event.changeEx; // get the export value\n";
|
|
osJsOnField << " if (idx != -1)\n";
|
|
osJsOnField << " {\n";
|
|
osJsOnField << " //console.println(\"thisfield.index: \" + idx);\n";
|
|
osJsOnField << " //console.println(\"thisfield.exportvalue: \" + thisfield.getItemAt(idx, true));\n";
|
|
osJsOnField << " //console.println(\"thisfield.value: \" + thisfield.getItemAt(idx, false));\n";
|
|
osJsOnField << " // listobj.data is : [nodeuid, icon] \n";
|
|
osJsOnField << " \n";
|
|
osJsOnField << " //. populate related text field\n";
|
|
osJsOnField << " textfield_partselected = this.getField(\"DF_PartSelected_" << sSuffixFields << "\");\n";
|
|
osJsOnField << " textfield_partselected.value = thisfield.getItemAt(idx, false);\n";
|
|
osJsOnField << " \n";
|
|
osJsOnField << " //. populate related button icon\n";
|
|
osJsOnField << " buticon = this.getField(\"DF_PartSelectedIcon_" << sSuffixFields << "\");\n";
|
|
osJsOnField << " buticon.display = display.visible;\n";
|
|
osJsOnField << " buticon.buttonPosition = position.iconOnly;\n";
|
|
osJsOnField << " iconname = lstObj_" << sFieldData.m_acName << ".data[idx][1];\n";
|
|
osJsOnField << " icon_i = this.getIcon(iconname);\n";
|
|
osJsOnField << " if (icon_i!=null) buticon.buttonSetIcon(icon_i);\n";
|
|
osJsOnField << " else buticon.buttonPosition = position.textOnly;\n";
|
|
osJsOnField << " \n";
|
|
osJsOnField << " //. highlight related 3d node (3d annot is supposed on the same page as the field)\n";
|
|
osJsOnField << " annot3d_related = this.getAnnots3D(event.target.page)[0];\n";
|
|
osJsOnField << " selectnode(annot3d_related, lstObj_" << sFieldData.m_acName << ".data[idx][0]);\n";
|
|
osJsOnField << " }\n";
|
|
osJsOnField << "}\n";
|
|
|
|
// For a listbox with correct slider behaviour, the JavaScript should be set on KeyStroke event.
|
|
CHECK_RET(A3DPDFPageFieldSetActionJavascript(pPage, sFieldData.m_acName, kA3DPDFEventFieldKeyStroke, osJsOnField.str().c_str()));
|
|
}
|
|
else if (string_equals(sFieldData.m_acName, "DF_PartsTitle_" + sSuffixFields) && bFieldParts)
|
|
{
|
|
CHECK_RET(A3DPDFPageFieldSetVisibility(pPage, sFieldData.m_acName, true));
|
|
}
|
|
else if (string_equals(sFieldData.m_acName, "DF_PartSelectedTitle_" + sSuffixFields) && bFieldParts)
|
|
{
|
|
CHECK_RET(A3DPDFPageFieldSetVisibility(pPage, sFieldData.m_acName, true));
|
|
}
|
|
else if (string_equals(sFieldData.m_acName, "DF_PartSelected_" + sSuffixFields) && bFieldParts)
|
|
{
|
|
CHECK_RET(A3DPDFPageFieldSetVisibility(pPage, sFieldData.m_acName, true));
|
|
}
|
|
else // unknown or unselected field - hiding it
|
|
{
|
|
CHECK_RET(A3DPDFPageFieldSetVisibility(pPage, sFieldData.m_acName, false));
|
|
}
|
|
}
|
|
A3DPDFPageGetFields(nullptr, &iNbFields,&ppFields);
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
|
|
A3DStatus BuildPDFDocument()
|
|
{
|
|
A3DStatus iRet = A3D_SUCCESS;
|
|
|
|
int indexpage = 0;
|
|
std::string sSuffixFields;
|
|
|
|
// creating a document
|
|
A3DPDFDocument* pDoc = NULL;
|
|
|
|
CHECK_RET(A3DPDFDocumentCreateEmpty(&pDoc));
|
|
|
|
if (pDoc != NULL)
|
|
{
|
|
A3DPDFPage* pPage = NULL;
|
|
|
|
// creating a poster image to be used as a poster for 3D.
|
|
A3DPDFImage* pBlankImage = NULL;
|
|
A3DPDFImageCreateFromFile(pDoc, POSTER_PATH, kA3DPDFImageFormatUnknown, &pBlankImage);
|
|
|
|
|
|
// create page idx+1 from template file. we force the fields renaming to avoid duplicated names.
|
|
sSuffixFields = "uuid0";
|
|
CHECK_RET(A3DPDFDocumentAppendPageFromPDFFileAndSuffixFields(pDoc, PDF_TEMPLATE, sSuffixFields.c_str(), &pPage));
|
|
if (pPage != NULL)
|
|
{
|
|
A3DPDF3DAnnot* p3DAnnot = NULL;
|
|
A3DPDF3DArtwork* p3DArtwork = NULL;
|
|
A3DAsmModelFile* pModelFile = NULL;
|
|
// To get unique IDs, we need a A3DRWParamsPrcWriteHelper.
|
|
// A3DPDF3DStreamCreateFromModelFileAsPRC builds this object.
|
|
A3DRWParamsPrcWriteHelper* pPRCWriteHelper = NULL;
|
|
CHECK_RET(Create3DAnnot(pDoc, IN_3DFILE, pBlankImage, NULL, &p3DArtwork, &p3DAnnot, &pPRCWriteHelper, &pModelFile));
|
|
|
|
bool bFieldTitle = true;
|
|
bool bFieldDate = true;
|
|
bool bFieldViews = true;
|
|
bool bFieldParts = false;
|
|
|
|
std::vector<std::vector<std::string> > aTable3DRows;
|
|
stPopulateDFTemplate(pDoc, pPage,
|
|
p3DArtwork, p3DAnnot,
|
|
sSuffixFields,
|
|
bFieldTitle, "Crank Instructions",
|
|
bFieldDate, "2013 oct 12",
|
|
bFieldViews,
|
|
bFieldParts, aTable3DRows);
|
|
|
|
// cleanup 3D modelfile
|
|
CHECK_RET(A3DAsmModelFileDelete(pModelFile));
|
|
// free the A3DRWParamsPrcWriteHelper object at the end
|
|
if (pPRCWriteHelper != NULL)
|
|
A3DRWParamsPrcWriteHelperFree(pPRCWriteHelper);
|
|
|
|
indexpage++;
|
|
}
|
|
|
|
|
|
// create page idx+1 from template file. we force the fields renaming to avoid duplicated names.
|
|
sSuffixFields = "uuid1";
|
|
CHECK_RET(A3DPDFDocumentAppendPageFromPDFFileAndSuffixFields(pDoc, PDF_TEMPLATE, sSuffixFields.c_str(), &pPage));
|
|
|
|
if (pPage != NULL)
|
|
{
|
|
A3DPDF3DAnnot* p3DAnnot = NULL;
|
|
A3DPDF3DArtwork* p3DArtwork = NULL;
|
|
A3DAsmModelFile* pModelFile = NULL;
|
|
// To get unique IDs, we need a A3DRWParamsPrcWriteHelper.
|
|
// A3DPDF3DStreamCreateFromModelFileAsPRC builds this object.
|
|
A3DRWParamsPrcWriteHelper* pPRCWriteHelper = NULL;
|
|
CHECK_RET(Create3DAnnot(pDoc, IN_3DFILE, pBlankImage, NULL, &p3DArtwork, &p3DAnnot, &pPRCWriteHelper, &pModelFile));
|
|
|
|
bool bFieldTitle = true;
|
|
bool bFieldDate = true;
|
|
bool bFieldViews = false;
|
|
bool bFieldParts = true;
|
|
|
|
std::vector<std::vector<std::string> > aTable3DRows;
|
|
|
|
// parse the 3D PDF nodes
|
|
A3DPDFModelFileNodesData* pModelFileNodesInfo = NULL;
|
|
CHECK_RET(A3DPDFGetModelFileNodes(pModelFile, pPRCWriteHelper, &pModelFileNodesInfo));
|
|
std::vector<std::string> mapOfNames;
|
|
|
|
int iFirstNode = 2; // for this sample, we don't take the 2 first nodes (node 0 is for the root, and node 1 doesn't exist)
|
|
for (size_t inodein3d = iFirstNode; inodein3d < (size_t)pModelFileNodesInfo->m_iNbNodes; inodein3d++)
|
|
{
|
|
A3DPDFNodeData* nodeInfos = pModelFileNodesInfo->m_ppNodes[inodein3d];
|
|
|
|
// in this sample, the 3D nodes involved in datamodel are the Product Occurences
|
|
// the product name is the key to bom entry
|
|
|
|
if (nodeInfos->m_eNodeType == kA3DPDFNodeProductOccurrence)
|
|
{
|
|
std::string sNodeName = nodeInfos->m_pcName;
|
|
std::string sIconId;
|
|
if (sNodeName == "01-2_CRANKSHAFT")
|
|
sIconId = "crank_crankshaft.jpg";
|
|
else if (sNodeName == "CONNECTING_ROD")
|
|
sIconId = "crank_connectingrod.jpg";
|
|
else if (sNodeName == "CONNECTING_ROD_CAP")
|
|
sIconId = "crank_connectingrod_cap.jpg";
|
|
else if (sNodeName == "CONNECTING_ROD_BUSHING")
|
|
sIconId = "crank_connectingrod_bushing.jpg";
|
|
else if (sNodeName == "CONNECTING_ROD_BOLT")
|
|
sIconId = "crank_connectingrod_bolt.jpg";
|
|
else if (sNodeName == "CONNECTING_ROD_BOLT_NUT")
|
|
sIconId = "crank_connectingrod_boltnut.jpg";
|
|
else if (sNodeName == "01-2_PISTON")
|
|
sIconId = "crank_piston.jpg";
|
|
else if (sNodeName == "01-2_PISTON_PIN")
|
|
sIconId = "crank_pistonpin.jpg";
|
|
else if (sNodeName == "01-2_PISTON_RETAINER")
|
|
sIconId = "crank_pistonretainer.jpg";
|
|
else if (sNodeName == "01-2_PISTON_TOP_COMP<01-2_PISTON_RING>")
|
|
sIconId = "crank_pistonring.jpg";
|
|
else if (sNodeName == "PISTON_BOT_COMP<01-2_PISTON_RING>")
|
|
sIconId = "crank_pistonring.jpg";
|
|
else if (sNodeName == "PISTON_OIL_COMP<01-2_PISTON_RING>")
|
|
sIconId = "crank_pistonring.jpg";
|
|
else if (sNodeName == "01-2_VALVE_TIMING_SPROCKET")
|
|
sIconId = "crank_valve.jpg";
|
|
else if (sNodeName == "01-2_DAMPER_PULLEY")
|
|
sIconId = "crank_damper.jpg";
|
|
// ...
|
|
// TODO: complete nodes treatment
|
|
|
|
// insert only once the nodes in the listbox
|
|
if (std::find(mapOfNames.begin(), mapOfNames.end(), sNodeName) == mapOfNames.end()) // not found : create entry
|
|
{
|
|
mapOfNames.push_back(sNodeName);
|
|
std::vector<std::string> aOneRow;
|
|
aOneRow.push_back(sNodeName);
|
|
aOneRow.push_back(nodeInfos->m_pcNodeUid);
|
|
aOneRow.push_back(sIconId);
|
|
aTable3DRows.push_back(aOneRow);
|
|
}
|
|
}
|
|
}
|
|
CHECK_RET(A3DPDFGetModelFileNodes(nullptr, nullptr, &pModelFileNodesInfo));
|
|
|
|
stPopulateDFTemplate(pDoc, pPage,
|
|
p3DArtwork, p3DAnnot,
|
|
sSuffixFields,
|
|
bFieldTitle, "Crank Parts",
|
|
bFieldDate, "2013 oct 12",
|
|
bFieldViews,
|
|
bFieldParts, aTable3DRows);
|
|
|
|
// cleanup 3D modelfile
|
|
CHECK_RET(A3DAsmModelFileDelete(pModelFile));
|
|
// free the A3DRWParamsPrcWriteHelper object at the end
|
|
if (pPRCWriteHelper != NULL)
|
|
A3DRWParamsPrcWriteHelperFree(pPRCWriteHelper);
|
|
|
|
indexpage++;
|
|
}
|
|
|
|
|
|
// store javascript functions on the document. these functions can be used by javascript stored on the fields.
|
|
std::ostringstream osJsOnDoc;
|
|
osJsOnDoc << "function activateview(a3d, viewname)\n";
|
|
osJsOnDoc << "{\n";
|
|
osJsOnDoc << " // activate the 3D annotation\n";
|
|
osJsOnDoc << " if (!a3d.activated) a3d.activated = true;\n";
|
|
osJsOnDoc << " c3d = a3d.context3D;\n";
|
|
osJsOnDoc << " if (c3d!=undefined)\n";
|
|
osJsOnDoc << " {\n";
|
|
osJsOnDoc << " c3d.runtime.setView(viewname, true);\n";
|
|
osJsOnDoc << " }\n";
|
|
osJsOnDoc << "}\n";
|
|
osJsOnDoc << "function selectnode(a3d, nodename)\n";
|
|
osJsOnDoc << "{\n";
|
|
osJsOnDoc << " //console.println(\"selecting node: \" + nodename);\n";
|
|
osJsOnDoc << " // activate the 3D annotation\n";
|
|
osJsOnDoc << " if (!a3d.activated) a3d.activated = true;\n";
|
|
osJsOnDoc << " c3d = a3d.context3D;\n";
|
|
osJsOnDoc << " if (c3d!=undefined)\n";
|
|
osJsOnDoc << " {\n";
|
|
osJsOnDoc << " scene = c3d.scene;\n";
|
|
osJsOnDoc << " var node = scene.nodes.getByName(nodename);\n";
|
|
osJsOnDoc << " if (node!=undefined) scene.selectedNode = node;\n";
|
|
osJsOnDoc << " }\n";
|
|
osJsOnDoc << "}";
|
|
CHECK_RET(A3DPDFDocumentAddJavascriptFromString(pDoc, "MyFns", osJsOnDoc.str().c_str()));
|
|
|
|
// add properties to the document
|
|
|
|
// end document
|
|
|
|
CHECK_RET(A3DPDFDocumentSaveEx(pDoc, kA3DPDFSaveFull | kA3DPDFSaveOptimized, OUT_FILE));
|
|
|
|
CHECK_RET(A3DPDFDocumentClose(pDoc));
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
|
|
|
|
//######################################################################################################################
|
|
// Main function
|
|
#ifdef _MSC_VER
|
|
int wmain(A3DInt32, A3DUniChar**)
|
|
#else
|
|
int main(int, A3DUTF8Char**)
|
|
#endif
|
|
{
|
|
#ifndef _MSC_VER
|
|
setenv("LC_NUMERIC", "en_US.UTF-8", 1); // Locally force locale
|
|
#endif
|
|
|
|
// init A3DLIB library - automatically handled init/terminate
|
|
A3DSDKHOOPSPublishLoader sHoopsPublishLoader(_T(HOOPS_BINARY_DIRECTORY));
|
|
CHECK_RET(sHoopsPublishLoader.m_eSDKStatus);
|
|
CHECK_RET(A3DDllSetCallbacksMemory(CheckMalloc, CheckFree));
|
|
|
|
// init HOOPS Publish related PDF library - automatically handled init/terminate
|
|
// do it only only once during the life of the application
|
|
CHECK_RET(sHoopsPublishLoader.InitPDFLib());
|
|
|
|
|
|
|
|
// launch PDF treatment
|
|
A3DStatus iRet = BuildPDFDocument();
|
|
if (iRet != A3D_SUCCESS)
|
|
return iRet;
|
|
|
|
// Check memory allocations
|
|
return (int)ListLeaks();
|
|
}
|