BIM Coordinator Program (INT) April 22, 2024
Find the next step in your career as a Graphisoft Certified BIM Coordinator!
Archicad C++ API
About Archicad add-on development using the C++ API.
SOLVED!

Ways of "choosing" an element on the floor plan and perform an action

BenjiDev
Enthusiast

Lets say there is an element on the floor plan (any type of element). In my Addon I want to "choose" that element and perform some action. For example display its name, show its type or whatever you can imagine. 

 

Ways of choosing the element that I know:

 

1. Create a dialog/palette with a button, clicking the button runs ACAPI_Interface(APIIo_GetPointID, point).

use point.neig.guid to get the clicked element and run your functionality. 
I think this method is very slow for the user.
 
2. Assign a global shortcut trough Work Environment/Keyboard Shortcuts to a command that triggers the MenuCommandHandler  (registered using ACAPI_Install_MenuHandler in Initialize) and get the selected element (using ACAPI_Selection_Get) and perform the action.

This works well, unless the user have a hard time finding a global shortcut that is not assigned to something else. 

 

3. I believe you can create shortcuts that is specific for your dialog/palette requiring the dialog/palette to be open but they won't conflict with the global shortcuts.

 

4. Use ACAPI_Notification_CatchSelectionChange and when an element you are interseted in gets selected, perform the action.  Can be bothersome if the user just wanted to select the element and not perform the action.

 

5. Somehow get notified when an element is double clicked, haven't found a way to do this. Probably not possible, but I hope I'm wrong.

 

6: Somehow make the action appear in the context menu of the element, haven't found a way to do this. Probably not possible, but I hope I'm wrong:

BenjiDev_0-1698320551746.png

7. If the element is a GDL object maybe it is possible to hack together a way to set a paramater when the user clicks/drags/double clicks inside an RECT2 or something. And have the addon listen to parameter changes on that object trough ACAPI_Element_InstallElementObserver. 

 

Just brainstorming, maybe some of these don't make sense. Let me know if you have other/better ideas.

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Solution

Hi Benji,

 

Great list! A few thoughts and other ideas:

  1. There are special pet-palettes (see ACAPI_Dialog_PetPalette) which might be useful. Haven't used them before so not 100% sure about everything.
    But I think they could be created when a user selects an object (combination with your 4th point), but that might still be too interruptive. This could be improved, by letting the user switch in and out of a special mode for your Add-On which enables the pet palette to show up on selection.
  2. You can add panels to the info box. They still have to be added to manually by the user via the work environment settings iirc, but that could be done once for a template. This is quite powerful I think and I've used it before once. You can let users change settings in there directly or add buttons to trigger actions. Check out the Panel_Test example and ACAPI_AddOnIntegration_InstallPanelHandler. (There's also the possibility to add panels to the Settings Dialog box).
  3. Concerning your 6th point about appearing in the context menu. You could "hijack" user interaction before it reaches Archicad (lots of different ways to do that, but nothing "native" to the Archicad C++ API) and then let that interaction trigger something in your Add-On (either directly send something to the Add-On or let the "hijacker" display your own context menu first on e.g. CTRL+Right Click). It's probably quite cumbersome to make that platform independent and I haven't tried it before so also not 100% sure if it even works properly.

Best,
Bernd

 

Bernd Schwarzenbacher - Archicad Add-On Developer - Get Add-Ons & Archicad Tips on my Website: Archi-XT.com

View solution in original post

4 REPLIES 4
Solution

Hi Benji,

 

Great list! A few thoughts and other ideas:

  1. There are special pet-palettes (see ACAPI_Dialog_PetPalette) which might be useful. Haven't used them before so not 100% sure about everything.
    But I think they could be created when a user selects an object (combination with your 4th point), but that might still be too interruptive. This could be improved, by letting the user switch in and out of a special mode for your Add-On which enables the pet palette to show up on selection.
  2. You can add panels to the info box. They still have to be added to manually by the user via the work environment settings iirc, but that could be done once for a template. This is quite powerful I think and I've used it before once. You can let users change settings in there directly or add buttons to trigger actions. Check out the Panel_Test example and ACAPI_AddOnIntegration_InstallPanelHandler. (There's also the possibility to add panels to the Settings Dialog box).
  3. Concerning your 6th point about appearing in the context menu. You could "hijack" user interaction before it reaches Archicad (lots of different ways to do that, but nothing "native" to the Archicad C++ API) and then let that interaction trigger something in your Add-On (either directly send something to the Add-On or let the "hijacker" display your own context menu first on e.g. CTRL+Right Click). It's probably quite cumbersome to make that platform independent and I haven't tried it before so also not 100% sure if it even works properly.

Best,
Bernd

 

Bernd Schwarzenbacher - Archicad Add-On Developer - Get Add-Ons & Archicad Tips on my Website: Archi-XT.com
BenjiDev
Enthusiast

Hey Bernd!

Thanks for the input!

1. Yes this would definitely be an improvement, but still a bit too interruptive. 

2. Nice, I did not think/know about this one.

3. Interesting idea, but very hacky 😄

 

After checking out Panel_Test I think adding a panel to the info box with a button (maybe in combination with adding a global shortcut that triggers the same action) is the better solution in regards with what the users are familiar with.

Best,

Benjamin

  

 

 

I spent yesterday trying to figure out how do work with ACAPI_AddOnIntegration_InstallPanelHandler, ACAPI_AddOnIntegration_RegisterInfoBoxPanel etc:

Some stuff:

1. "They still have to be added to manually by the user via the work environment settings iirc" ACAPI_AddOnIntegration_RegisterInfoBoxPanel takes a flag that indicates if they should appear by default. So that is nice.

2. The Panel_Test is quite verbose and I think it does some unnecessary stuff, like managing a global pointer TestInfoBoxPanel* infoBoxPanel. 

This is how i do it:

 

static GSErrCode __ACENV_CALL
CreatePageCallback(Int32, const void *tabControl, void *, void **tabPage)
{

    const DG::TabControl *control =
        reinterpret_cast<const DG::TabControl *>(tabControl);
    DG::TabPage **page = reinterpret_cast<DG::TabPage **>(tabPage);
    *page              = new TextToolsTabPage(*control);
    gTabPageOpen       = true;
    return NoError;
}

static GSErrCode __ACENV_CALL DestroyPageCallback(Int32, void *tabPage)
{
    DG::TabPage *page = reinterpret_cast<DG::TabPage *>(tabPage);
    delete page;
    gTabPageOpen = false;
    return NoError;
}

 

 

If I understand it correctly, you are suppose to allocate tabPage yourself and free it when DestroyPageCallback is run (called when user deselects the element for example).

3.  In my case i wanted to read and change the memo.textContent of the selected element when a button is clicked in the tabpage.

And the third argument in CreatePageCallback can be cast to TBUI::IAPIToolUIData* which have these functions:

 

GetAPIElement (void* APIElemData, void* APIElemMemoData = nullptr) = 0;
SetAPIElement (void* APIElemData, const void * elemMask, void* APIElemMemoData = nullptr, Int32 memoMask = 0) = 0;

 

Which tells me what I want to do is possible. I don't understand why the arguments are void* pointers though, can there be cases where they return other things than API_Element, API_ElementMemo etc? Anyway I did not find any documentation about it. These are used in the example to modify a wall, but when calling GetAPIElement the memo is empty, so i cannot get memo.textContent. And element.header.guid and element.text.head.guid are empty so i can't get the memo using those. But element.text is filled in correctly, so I probably did something wrong, but on the other hand I encounter same behaviour in Panel_Test. Anyway, a work-around was to ignore everything that had to do with TBUI::IAPIToolUIData* and just get the selected texts using ACAPI_Selection_Get when the button in the tabpage was pressed.  
 
4. I had crashes in VBElemDialogs.dll  (the module related to IAPIToolUIData etc...) when the tabpage was opened at the same time the addon was unloaded (for example when the user triggered the MenuCommandHandler). I think something weird is happening with tabPage in the server application when the addon is unloaded before DestroyPageCallback is called. Anyway I solved it by calling ACAPI_KeepInMemory in MenuCommandHandler if gTabPageOpen. Does not feel like a good solution but it resolves the crashes.
 
5. DG::TabPage inherits from DG::Panel which have facilities for adding hotkeys. So maybe you can use these instead of global shortcuts.
 
Best,
Benjamin

 

 
 
Botonis
Advisor

In my opinion as a user, for something that is used often, the keyboard shortcut is the fastest way. While you assign a shortcut there is the check control if this is already assigned or not. The shortcut combination can be anything so you have thousands of options that will not conflict with already defined ones.

If you have a macro mouse you can even assign the shortcut to a mouse macro key. 

Botonis Botonakis
Civil Engineer, Enviromental Design MSc., BIM Manager for BS ArhitectsVR
Company or personal website
Archicad 27. Windows 11. Intel Xeon 2699x2,64 GB RAM, Nvidia 3080Ti. 2 Monitors.
Learn and get certified!