cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Begin your Archicad journey with our free learning path - perfect for newcomers and experienced users looking to strenghten their skills.

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

why NotificationHandler of ACAPI_ProjectOperation_CatchProjectEvent get zero body?

sxs
Booster

  Hi, everyone:
  first, this is part of my code:

static GSErrCode NotificationHandler(API_NotifyEventID notifID, Int32 param)
{
	char    msgStr[256];

	switch (notifID) {
	case APINotify_New:                CHCopyC("APINotify_New", msgStr);             break;
	case APINotify_NewAndReset:        CHCopyC("APINotify_NewAndReset", msgStr);     break;
	case APINotify_Open:               CHCopyC("APINotify_Open", msgStr);            break;
	case APINotify_PreSave:            CHCopyC("APINotify_PreSave", msgStr);         break;
	case APINotify_Save:               CHCopyC("APINotify_Save", msgStr);            break;
	case APINotify_Close:              CHCopyC("APINotify_Close", msgStr);           break;
	case APINotify_Quit:               CHCopyC("APINotify_Quit", msgStr);            break;

	case APINotify_SendChanges:        CHCopyC("APINotify_SendChanges", msgStr);     break;
	case APINotify_ReceiveChanges:     CHCopyC("APINotify_ReceiveChanges", msgStr);  break;

	case APINotify_ChangeProjectDB:    CHCopyC("APINotify_ChangeProjectDB", msgStr); break;
	case APINotify_ChangeWindow:       CHCopyC("APINotify_ChangeWindow", msgStr);    break;
	case APINotify_ChangeFloor:        CHCopyC("APINotify_ChangeFloor", msgStr);     break;
	case APINotify_ChangeLibrary:      CHCopyC("APINotify_ChangeLibrary", msgStr);   break;
	case APINotify_AllInputFinished:      CHCopyC("APINotify_AllInputFinished", msgStr);   break;
	}

	//
	void* origSight;
	auto err = ACAPI_Sight_SelectSight(nullptr, &origSight);
	if (err != NoError) {
		//ErrorBeep("Cannot switch to the 3D sight", err);
		ACAPI_WriteReport("Cannot switch to the 3D sight", true);
		return err;
	}
	//
	{
          Int32		nbody;
          err = ACAPI_ModelAccess_GetNum (API_BodyID, &nbody);// nbody is zero, but there are many elements
        }

	ACAPI_WriteReport(msgStr, true);

	return NoError;
}   // NotificationHandler


API_AddonType CheckEnvironment (API_EnvirParams* envir)
{
	RSGetIndString (&envir->addOnInfo.name, ID_ADDON_INFO, 1, ACAPI_GetOwnResModule ());
	RSGetIndString (&envir->addOnInfo.description, ID_ADDON_INFO, 2, ACAPI_GetOwnResModule ());

	return APIAddon_Preload;// this is important
}		// CheckEnvironment

GSErrCode Initialize	(void)
{	
        auto err = ACAPI_ProjectOperation_CatchProjectEvent(APINotify_AllInputFinished, NotificationHandler);

	return NoError;
}		// Initialize

   my goal is to get geometry of all elements in NotificationHandler,but it does not works, the count of Body i get is zero.

   so, what's wrong with the code.

2 ACCEPTED SOLUTIONS

Accepted Solutions
Solution

Try bringing the 3D window to the front (see my separate reply on a different thread) and then use ACAPI_View_Rebuild. I think you may need to pass a true value in the doRebuildAndRegenerate parameter.

Ralph Wessel BArch
Central Innovation

View solution in original post

Solution
	//
	{
		API_WindowInfo      windowInfo;
		API_DatabaseInfo    origDB, planDB;
		API_Element         element;
		GS::Array<API_Guid> elemList;
		GSErrCode           err;

		BNZeroMemory(&planDB, sizeof(API_DatabaseInfo));
		planDB.typeID = APIWind_3DModelID;

		//ACAPI_Database(APIDb_GetCurrentDatabaseID, &origDB, nullptr);
		ACAPI_Database_ChangeCurrentDatabase(&planDB);
		//
		BNZeroMemory(&windowInfo, sizeof(API_WindowInfo));
		windowInfo.typeID = APIWind_3DModelID;
		windowInfo.databaseUnId = planDB.databaseUnId;
		err = ACAPI_Window_ChangeWindow(&windowInfo);
	}
	//
	if (err == NoError)
	{
		bool is_rebuild = true;
		ACAPI_View_Rebuild(&is_rebuild);
	}
	//
	{
		{
			void* origSight;
			GSErrCode	err;

			err = ACAPI_Sight_SelectSight(nullptr, &origSight);
		}

		//
		Int32 nbody;
		auto err = ACAPI_ModelAccess_GetNum(API_BodyID, &nbody);

		WriteReport_Alert("body num %d", nbody);
	}

 

sxs_0-1748509658786.png

 

View solution in original post

11 REPLIES 11

The function ACAPI_ModelAccess_GetNum will count the number of bodies in the 3D view - is anything displayed in the 3D view when you call it? Also, have you checked if an error code is returned from the function?

 

As an aside, I wouldn't use this function every time a project notification is emitted - otherwise this will be called repeatedly for no purpose. Also don't forget to call ACAPI_Sight_SelectSight afterward to switch back to the original view when you've collected the data.

Ralph Wessel BArch
Central Innovation
sxs
Booster

Hi,

    1,This is the 3d model:

sxs_0-1747966335962.png

   I don't know if I called it at the wrong time, but I can get wall by this code:

GS::Array<API_Guid> wallList;
ACAPI_Element_GetElemList(API_WallID, &wallList);

2,I have confirmed that it returned NoError.

 


@sxs wrote:

   I don't know if I called it at the wrong time, but I can get wall by this code:

GS::Array<API_Guid> wallList;
ACAPI_Element_GetElemList(API_WallID, &wallList);

2,I have confirmed that it returned NoError.

 


I need to know a bit more about you are planning to develop to answer the question properly. Do you want 3D geometry (bodies, faces, vertices etc) or information about the construction elements in the project? I'm asking because the 2 commands you mentioned (ACAPI_ModelAccess_GetNum and ACAPI_Element_GetElemList) extract data from two different sources:

  1. Project database: This is the data that persists when you save an Archicad project. This is designed to contain as little raw 3D geometry as possible - instead, elements are described by parameters and metadata. The 2D/3D geometry is only created on demand when you open and view the project. This data is obtained using commands like ACAPI_Element_GetElemList. The data returned by these functions will not change unless new elements are created, edited or deleted, e.g. the number of walls returned by ACAPI_Element_GetElemList won't change unless a wall is added/removed in the project database.
  2. Model database: This data is only created on demand (never saved in the project) and can vary according to what the user is currently viewing. If you select 3 elements and view them in 3D, the model database will contain only 3 objects (irrespective of the project database content). This data is retrieved with functions like ACAPI_ModelAccess_GetNum, and the returned values will change dynamically according to the 3D window content, e.g. if the 3D window is empty/unpopulated, ACAPI_ModelAccess_GetNum will return 0.
Ralph Wessel BArch
Central Innovation

Thank you, I understand now。

 

want 3D geometry (bodies, faces, vertices etc), so What api is suitable for me?

 How to get 3D geometry (bodies, faces, vertices etc)  in NotificationHandler of project notification?

 Maybe you would recommend ACAPI_Sight_SelectSight, but I've tried it and it didn't work。


@sxs wrote:

 How to get 3D geometry (bodies, faces, vertices etc)  in NotificationHandler of project notification?

 Maybe you would recommend ACAPI_Sight_SelectSight, but I've tried it and it didn't work。


it would help to understand what you want to do. I suspect that using project event notifications (open, save, close etc) are probably not what you want, but I can't definitely say without knowing why you want the 3D geometry. If a user has just opened a project (for example) the model will always be empty because it hasn't been viewed yet. Archicad doesn't automatically do this because building 3D geometry can be very processor-intensive and it's wasted until the user has actually asked to see something specific in 3D.

If you want to export the 3D geometry in a different format (for example) then there are APIs for plugging directly into Archicad's 'Save As…' functionality. If you explain what you would like to do, I could point in the best direction for accomplishing it.

Ralph Wessel BArch
Central Innovation

“If you want to export the 3D geometry in a different format (for example)”, it is my goal, but I want to do this without any user operation like clicking menu button, I want to create an automic plugin to export the 3D geometry in a different format. The automation plugin means that once Archicad completes opening the model file, the plugin will run directly without any user intervention like clicking menu button.

Solution

Try bringing the 3D window to the front (see my separate reply on a different thread) and then use ACAPI_View_Rebuild. I think you may need to pass a true value in the doRebuildAndRegenerate parameter.

Ralph Wessel BArch
Central Innovation

Okay, thank you. I'll give it a try

Didn't find the answer?

Check other topics in this Forum

Back to Forum

Read the latest accepted solutions!

Accepted Solutions

Start a new conversation!