We value your input!
Please participate in Archicad 28 Home Screen and Tooltips/Quick Tutorials survey

Archicad C++ API
About Archicad add-on development using the C++ API.

Import external detail

Dejmas
Participant
Hello developers,
my goal is to import an external DWG file as a drawing in a new detail window. This is very trivial to do as a user, but I am having an issue with doing it programmatically.
As I have understood in the documentation I can't just create a new drawing element and bind a link to it. I should rather use a call to DXF/DWG add-on and it is where I got stuck on.

I haven't found much about that. Just one example in the documentation where a dwg file is imported as lib part. So I tried similar to create a drawing. Can I get some advice from you?

Trying to run DXF/DWG add-on between APIDb_StartDrawingDataID and APIDb_StopDrawingDataID calls.

class IDFSession {

private:
	bool    inited;

public:
	explicit IDFSession() {
		inited = (ACAPI_Database(APIDb_StartDrawingDataID, nullptr, nullptr) == NoError);
	}

	~IDFSession() {
		if (inited) {
			GSPtr outIDFData = nullptr;
			if (GetIDFData(&outIDFData, nullptr))
				BMKillPtr(&outIDFData);
		}
	}

	bool GetIDFData(GSPtr *outIDFData, API_Box *bounds) {
		if (!inited || outIDFData == nullptr)
			return false;

		bool ret = (ACAPI_Database(APIDb_StopDrawingDataID, outIDFData, bounds) == NoError);

		inited = false;
		return ret;
	}
};

GSErrCode ImportDrawing()
{
	IDFSession  idfSession;                      // 1

	GSErrCode   ret = ReadAction();              // 2

	if (ret == NoError) {
		API_Box bounds = { 0.0, 0.0, 0.0, 0.0 };
		GSPtr   idfData = nullptr;

		if (idfSession.GetIDFData(&idfData, &bounds)) {    // 3
			CreateDrawing_UndoableCall(idfData, bounds);   // 4
		} else {
			WriteReport("No drawing data.");
		}
	}

	return ret;
}

static GSErrCode		ReadAction(void)
{
	API_ModulID	mdid = { 1198731108, 1322668197 };		// DXF/DWG add-on
	GSErrCode	err;

	double scale = 100.0;
	bool rebuild = false;
	err = ACAPI_Database(APIDb_ChangeDrawingScaleID, &scale, &rebuild);
	if (err != NoError) {
		WriteReport("Error in APIDb_ChangeDrawingScaleID: %s", ErrID_To_Name(err));
		return err;
	}

	IO::Location dwgFileLoc;
	if (!GetOpenFile(&dwgFileLoc, "dwg", "*.dwg"))
		return Cancel;
	
	// call the Dxf add-on
	GSHandle parHdl;
	err = ACAPI_Goodies(APIAny_InitMDCLParameterListID, &parHdl);
	if (err == NoError) {
		IO::URL url;
		dwgFileLoc.ToURL(&url);

		API_MDCLParameter par;
		BNZeroMemory(&par, sizeof(par));
		par.name = "FileName";
		par.type = MDCLPar_string;

		char str[512] = { 0 };
		CHTruncate((const char*)url, str, sizeof(str));
		par.string_par = str;

		err = ACAPI_Goodies(APIAny_AddMDCLParameterID, parHdl, &par);

		if (err == NoError)
			err = ACAPI_Command_Call(&mdid, 'OOBJ', 1, parHdl, nullptr, true);
	}

	ACAPI_Goodies(APIAny_FreeMDCLParameterListID, &parHdl);
	
	return err;
}		// ReadAction
I am not sure about my command call, maybe I just need a different cmdID. I haven't found any documentation for it. Maybe I should focus on if I can use a lib part to create drawing from. I will be glad for every opinion.

Thank you for your attention.
1 REPLY 1
Ralph Wessel
Mentor
Your overall process (using the existing DXF/DWG importer) is correct. I've only used this add-on through the API for creating library parts (as the example shows), so I can't say for sure that it can import as a plain drawing. However, if you don't find any way to make that work, you could place the DWG as a library part and then use the API to explode it into constituent parts, e.g. ACAPI_LibPart_ShapePrims or ACAPI_Element_ShapePrims.
Ralph Wessel BArch
Software Engineer Speckle Systems