4 weeks ago - last edited 4 weeks ago
Hello,
I successfully create a GSM object in Archicad Library, but I don't find a way to export it (or directly create it) on my computer.
Currently, I set the API_LibPart.location in the embeddedLibrary. I tried to set the location on a computer folder and it doesn't work (I get an error -2130312314), I suppose I need to create it in Archicad before exporting it, am I correct?
Solved! Go to Solution.
Tuesday
- last edited
Wednesday
by
Laszlo Nagy
Hi,
I found a solution from the LibPart_Test:
GS::Array<API_LibraryInfo> libInfo;
ACAPI_LibraryManagement_GetLibraries(&libInfo);
IO::Location folderLoc;
/*API_SpecFolderID specID = API_UserDocumentsFolderID;
ACAPI_ProjectSettings_GetSpecFolder(&specID, &folderLoc);*/
folderLoc = *(new IO::Location());
folderLoc.Set(GS::UniString("D:\\"));
folderLoc.AppendToLocal(IO::Name("LibPart_Test Library"));
IO::Folder destFolder(folderLoc, IO::Folder::Create);
libPart.location = new IO::Location(folderLoc);
bool vari = true;
for (UInt32 ii = 0; ii < libInfo.GetSize(); ii++) {
if (folderLoc == libInfo[ii].location)
vari = false;
}
if(vari)
{
API_LibraryInfo li;
li.location = folderLoc;
libInfo.Push(li);
ACAPI_LibraryManagement_SetLibraries(&libInfo);
}
const GS::UnID unID = BL::BuiltInLibraryMainGuidContainer::GetInstance().GetUnIDWithNullRevGuid(BL::BuiltInLibPartID::ModelElementLibPartID);
CHCopyC(unID.ToUniString().ToCStr(), libPart.parentUnID); // Model Element subtype
GSTimeRecord timeRecord;
TIGetTimeRecord(0, &timeRecord, TI_CURRENT_TIME);
UInt32 fraction = TIGetTicks() % TIGetTicksPerSec();
GS::snuprintf(libPart.docu_UName, sizeof(libPart.docu_UName) / sizeof(GS::uchar_t), L("LPTest_%d-%02d-%02d_%02d%02d%02d_%d"),
timeRecord.year, timeRecord.month, timeRecord.day, timeRecord.hour, timeRecord.minute, timeRecord.second, fraction);
ACAPI_LibraryPart_Create(&libPart);
//Create the libPart here, like in the code in my previous message on this thread
ACAPI_LibraryPart_Save(&libPart);
I suspect the problem come from using GS::ucscpy instead of GS::snuprintf, or maybe using API_LibraryInfo to set the library created.
But it works so I'm happy with it ! I get a GSM file at "D:\LibPart_Test Library".
Thanks again for your help @Oleg
4 weeks ago
I dont understood your issue exactly, so just a reply about the error code.
See ErrorCodes page of API documentation.
Error -2130312314 means APIERR_NESTING "The API function is not reentrant. Nesting occurred."
I think it is not location issue.
4 weeks ago
- last edited
3 weeks ago
by
Laszlo Nagy
Hello and thanks for the reply.
I've the error -2130313215 the first time I execute my code, then -2130312314 all the next time in the same Archicad instance.
The base of my code come from Speckle connector for Archicad, their methods GetLocation() and CreateSubFolder() work fine to create a library part in the embedded library, it failed when I try to set a Windows path. Source code: https://github.com/specklesystems/speckle-archicad/blob/release/3.0.0/AddOns/Speckle/Sources/AddOn/C...
The code I tried:
API_LibPart libPart;
BNClear(libPart);
BNZeroMemory(&libPart, sizeof(API_LibPart));
libPart.typeID = APILib_ObjectID;
libPart.isTemplate = false;
libPart.isPlaceable = true;
//Location part
IO::Location* loc = new IO::Location();
loc->Set(GS::UniString("D:\\Test")); //The path I want
libPart.location = loc;
CHCopyC("{57B7C584-5C0D-11D6-A0D8-036F034B6791}-{00000000-0000-0000-0000-000000000000}", libPart.parentUnID); // General Stair subtype
GS::ucscpy(libPart.docu_UName, L("Test LibPart")); //library part name
ACAPI_LibraryPart_Create(&libPart); //This method return the error
3 weeks ago
Hi
Is this all your code for test ?
PS:
LibPart creation is a building process, starts by ACAPI_LibraryPart_Create and ends by ACAPI_LibraryPart_Save.
LibPart's sections are created between them.
Like in Sparcle's LibpartBuilder::CreateLibPart method.
3 weeks ago
Tried the your code above.
But added ACAPI_LibraryPart_Save to avoid -2130312314 error.
It works for me (although it wasn't AC28).
If I change drive letter to non-existent on my PC, I got -2130313215 error.
May be you dont have "D" drive.
2 weeks ago
- last edited
2 weeks ago
by
Laszlo Nagy
Hello and thank you,
I have the D on my computer, and yes my full code is longer. For now I'm testing to create a simple box with a custom parameter.
Everything works when I create it in the embedded library, but when I try to set the path I always got the "-2130313215" error at "ACAPI_LibraryPart_Save(&libPart);".
I created a folder "C:\Test" on my computer.
Note I have the error "-2130312310" when tried with path "C://", I suppose I cannot write directly on C.
My full code :
---------------------------------------------------
void CreateGSM()
{
API_LibPart libPart;
BNClear(libPart);
BNZeroMemory(&libPart, sizeof(API_LibPart));
libPart.typeID = APILib_ObjectID;
libPart.isTemplate = false;
libPart.isPlaceable = true;
IO::Location* loc = new IO::Location();
loc->Set(GS::UniString("C:\\Test")); //or "C:\\Test\\"
libPart.location = loc;
CHCopyC("{57B7C584-5C0D-11D6-A0D8-036F034B6791}-{00000000-0000-0000-0000-000000000000}", libPart.parentUnID); // General Stair subtype
GS::ucscpy(libPart.docu_UName, L("Test LibPart"));
CHECK_ERROR(ACAPI_LibraryPart_Create(&libPart));
API_LibPartSection section;
GS::String line;
// Copyright section
BNZeroMemory(§ion, sizeof(API_LibPartSection));
section.sectType = API_SectCopyright;
CHECK_ERROR(ACAPI_LibraryPart_NewSection(§ion));
line = "Test Author"; // Author
CHECK_ERROR(ACAPI_LibraryPart_WriteSection(line.GetLength(), line.ToCStr()));
CHECK_ERROR(ACAPI_LibraryPart_EndSection());
// 3D script section
BNZeroMemory(§ion, sizeof(API_LibPartSection));
section.sectType = API_Sect3DScript;
CHECK_ERROR(ACAPI_LibraryPart_NewSection(§ion));
line = "block 1,1,1";
CHECK_ERROR(ACAPI_LibraryPart_WriteSection(line.GetLength(), line.ToCStr()));
CHECK_ERROR(ACAPI_LibraryPart_EndSection());
// Parameter script section
BNZeroMemory(§ion, sizeof(API_LibPartSection));
section.sectType = API_SectVLScript;
ACAPI_LibraryPart_NewSection(§ion);
ACAPI_LibraryPart_EndSection();
//Parameters script
BNZeroMemory(§ion, sizeof(API_LibPartSection));
section.sectType = API_SectParamDef;
short nPars = 2;
API_AddParType** addPars = reinterpret_cast<API_AddParType**>(BMAllocateHandle(nPars * sizeof(API_AddParType), ALLOCATE_CLEAR, 0));
if (addPars != nullptr)
{
API_AddParType* pAddPar = &(*addPars)[0];
pAddPar->typeID = APIParT_RealNum;
pAddPar->typeMod = 0;
CHTruncate("SklTestParameter", pAddPar->name, sizeof(pAddPar->name));
GS::ucscpy(pAddPar->uDescname, L("Test Parameter"));
pAddPar->value.real = 1;
double aa = 1.0;
double bb = 1.0;
GSHandle sectionHdl = nullptr;
ACAPI_LibraryPart_GetSect_ParamDef(&libPart, addPars, &aa, &bb, nullptr, §ionHdl);
API_LibPartDetails details;
BNZeroMemory(&details, sizeof(API_LibPartDetails));
details.object.autoHotspot = false;
details.object.fixSize = true;
ACAPI_LibraryPart_SetDetails_ParamDef(&libPart, sectionHdl, &details);
ACAPI_LibraryPart_AddSection(§ion, sectionHdl, nullptr);
BMKillHandle(reinterpret_cast<GSHandle*>(&addPars));
BMKillHandle(§ionHdl);
}
else
{
ACAPI_WriteReport("Failed to allocate memory for LibPart parameter.", true);
return;
}
// Save the constructed library part
CHECK_ERROR(ACAPI_LibraryPart_Save(&libPart));
}
---------------------------------------------------
In a different .h file:
---------------------------------------------------
#pragma once
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#ifndef CHECK_ERROR
#define CHECK_ERROR(f)\
{\
GSErrCode err = (f);\
if (err != NoError)\
{\
GS::UniString message = "Error in: " + GS::UniString(TOSTRING(f)) + ", Code: " + GS::ValueToUniString(err); \
ACAPI_WriteReport(message, true);\
}\
}
#endif
---------------------------------------------------
Thank you
2 weeks ago
I dont know a reason, sorry.
Just a last guess.
May be you run the test on demo archicad and may be the ACAPI_LibraryPart_Save has limitation.
2 weeks ago
Ok no problem, no I'm not on demo because I was afraid of the same thing, I have a full licence and my AddOn has a valid MDID.
Maybe its just obsolete in Archicad 28.4001 ? There is this message in the Documentation : Legacy function - to be deleted in future versions, use ACAPI::LM::GSMObject setters instead https://graphisoft.github.io/archicad-api-devkit/group___library_part.html#ga9d6ed5258ccb9669ce890e7...
I'll try again and send the result here if I found something.
Thanks again for all your answers.
Tuesday
- last edited
Wednesday
by
Laszlo Nagy
Hi,
I found a solution from the LibPart_Test:
GS::Array<API_LibraryInfo> libInfo;
ACAPI_LibraryManagement_GetLibraries(&libInfo);
IO::Location folderLoc;
/*API_SpecFolderID specID = API_UserDocumentsFolderID;
ACAPI_ProjectSettings_GetSpecFolder(&specID, &folderLoc);*/
folderLoc = *(new IO::Location());
folderLoc.Set(GS::UniString("D:\\"));
folderLoc.AppendToLocal(IO::Name("LibPart_Test Library"));
IO::Folder destFolder(folderLoc, IO::Folder::Create);
libPart.location = new IO::Location(folderLoc);
bool vari = true;
for (UInt32 ii = 0; ii < libInfo.GetSize(); ii++) {
if (folderLoc == libInfo[ii].location)
vari = false;
}
if(vari)
{
API_LibraryInfo li;
li.location = folderLoc;
libInfo.Push(li);
ACAPI_LibraryManagement_SetLibraries(&libInfo);
}
const GS::UnID unID = BL::BuiltInLibraryMainGuidContainer::GetInstance().GetUnIDWithNullRevGuid(BL::BuiltInLibPartID::ModelElementLibPartID);
CHCopyC(unID.ToUniString().ToCStr(), libPart.parentUnID); // Model Element subtype
GSTimeRecord timeRecord;
TIGetTimeRecord(0, &timeRecord, TI_CURRENT_TIME);
UInt32 fraction = TIGetTicks() % TIGetTicksPerSec();
GS::snuprintf(libPart.docu_UName, sizeof(libPart.docu_UName) / sizeof(GS::uchar_t), L("LPTest_%d-%02d-%02d_%02d%02d%02d_%d"),
timeRecord.year, timeRecord.month, timeRecord.day, timeRecord.hour, timeRecord.minute, timeRecord.second, fraction);
ACAPI_LibraryPart_Create(&libPart);
//Create the libPart here, like in the code in my previous message on this thread
ACAPI_LibraryPart_Save(&libPart);
I suspect the problem come from using GS::ucscpy instead of GS::snuprintf, or maybe using API_LibraryInfo to set the library created.
But it works so I'm happy with it ! I get a GSM file at "D:\LibPart_Test Library".
Thanks again for your help @Oleg