Skip to content

Interactor PythonPart

Creating a PythonPart as an interactor allows you to have full control over the entire workflow and full access to the provided Allplan Python-API. The workflow can contain functions like:

  • change the Allplan project
  • load a drawing file
  • select an existing element
  • execute a point input
  • create a new element (line, wall, PythonPart, …)
  • execute an IFC, DWG, PDF, … import or export

The interactor PythonPart allows workflows to be automated and offers the possibility of creating functionalities that does not currently exist in Allplan.

Required functions

To make the interactor visible for the PythonParts framework, the tag <Interactor> must be set to True in the xxx.pyp file:

<Script>
        <Interactor>True</Interactor>
</Script>

The python source code in the .py file must contain at least these two functions:

  • check_allplan_version - for checking the compatibility with current Allplan version. The implementation is just the same as in the standard PythonPart.
  • create_interactor - the function for the interactor creation. It must return an Interactor, which has to be implemented as a Python class.

create_interactor(coord_input, pyp_path, global_str_table_service, build_ele_list, build_ele_composite, control_props_list, modify_uuid_list)

Function for the interactor creation, called when PythonPart is initialized. When called, the PythonPart framework performs the following steps:

  • reads the parameters and their values from the xxx.pyp file and stores them in the buld_ele_list
  • if tag ReadLastInput is set to True: read the parameter values from the last input, (stored in ...\Usr_user_name_\tmp_python_part_name.pyv) and assign them to the parameters in build_ele_list
  • if starting an input by Match from the context menu or double right click: read the parameter values from the attribute @611@ of the matched PythonPart and assign them to the parameters in build_ele_list
  • if in modification mode: read the parameter values from the attribute @611@ of the selected PythonPart and assign them to the parameters in build_ele_list

Parameters:

Name Type Description Default
coord_input CoordinateInput

coordinate input

required
pyp_path str

path of the pyp file

required
global_str_table_service StringTableService

global string table service for default strings

required
build_ele_list List[BuildingElement]

list with the building elements containing parameter properties

required
build_ele_composite BuildingElementComposite

building element composite

required
control_props_list List[ControlProperties]

control properties list

required
modify_uuid_list List[str]

UUIDs of the existing elements in the modification mode

required

Returns:

Type Description
...

Created interactor object

Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def create_interactor(coord_input:                 AllplanIFWInput.CoordinateInput,
                      pyp_path:                    str,
                      global_str_table_service:    StringTableService,
                      build_ele_list:              typing.List[BuildingElement],
                      build_ele_composite:         BuildingElementComposite,
                      control_props_list:          typing.List[ControlProperties],
                      modify_uuid_list:            typing.List[str]) -> ...:
    """Function for the interactor creation, called when PythonPart is initialized.
    When called, the PythonPart framework performs the following steps:

    - reads the parameters and their values from the xxx.pyp file and stores them in the buld_ele_list
    - if tag `ReadLastInput` is set to True: read the parameter values from the last input,
        (stored in ...\\Usr\\_user_name_\\tmp\\_python_part_name.pyv) and assign them to the parameters
        in build_ele_list
    - if starting an input by Match from the context menu or double right click: read the parameter
        values from the attribute @611@ of the matched PythonPart and assign them to the parameters
        in build_ele_list
    - if in modification mode: read the parameter values from the attribute @611@ of the selected
        PythonPart and assign them to the parameters in build_ele_list

    Args:
        coord_input:               coordinate input
        pyp_path:                  path of the pyp file
        global_str_table_service:  global string table service for default strings
        build_ele_list:            list with the building elements containing parameter properties
        build_ele_composite:       building element composite
        control_props_list:        control properties list
        modify_uuid_list:          UUIDs of the existing elements in the modification mode

    Returns:
        Created interactor object
    """

    return Interactor(coord_input, pyp_path, global_str_table_service, build_ele_list,
                      build_ele_composite, control_props_list, modify_uuid_list)

Example

An example for this implementation can be found in:

  • …\etc\Examples\PythonParts\InteractorExamples*LinesFromFileInteractor.pyp*
  • …\etc\PythonPartsExampleScripts\InteractorExamples*LinesFromFileInteractor.py*

Tip

We do not recommend using the old, shorter implementation of the create_interactor function (shown below) that uses only three arguments. It does not offer e.g., the possibility of a modification mode of the created PythonPart. We reccomend using only the longer implementation with 7 arguments. If you don't need all of them, just don't use them in the __init__() function of your interactor class. Still, you can encounter the short implementation in some old examples.

def create_interactor(coord_input:              AllplanIFWInput.CoordinateInput,
                      pyp_path:                 str,
                      global_str_table_service: StringTableService) -> object:

    return Interactor(...)

Optional functions

To create elements, which should be displayed in the Allplan library as a preview, implement the function create_preview into your script. See the chapter Library preview to learn more about creating preview in the Allplan library.

create_preview(build_ele, doc)

Parameters:

Name Type Description Default
build_ele BuildingElement

building element with the parameter properties

required
doc DocumentAdapter

document of the Allplan drawing files

required

Returns:

Type Description
CreateElementResult

created element result

Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def create_preview(build_ele:   BuildingElement,
                   doc:         AllplanElementAdapter.DocumentAdapter) -> CreateElementResult:
    """ Create the library preview

    Args:
        build_ele: building element with the parameter properties
        doc:       document of the Allplan drawing files

    Returns:
        created element result
    """
    return CreateElementResult(elements=[...])

Interactor class

An interactor PythonPart must be implemented as a Python class and the constructed object of this class must be returned by the create_interactor function. Depending on actions done by the user in Allplan (moving the mouse, changing property in the palette, etc.) certain methods will be called. The implementation of these methods will determine the behavior of the PythonPart. Below is the description of all of them. Some of these methods are obligatory to be implemented in your Interactor class. Alternatively, they can be inherited from the BaseInteractor class (see this paragraph to learn how to do it).

Interactor

Template of an Interactor class

Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
class Interactor(BaseInteractor):
    """ Template of an Interactor class """

    def __init__(self,
                coord_input:                AllplanIFWInput.CoordinateInput,
                pyp_path:                   str,
                global_str_table_service:   StringTableService,
                build_ele_list:             typing.List[BuildingElement],
                build_ele_composite:        BuildingElementComposite,
                control_props_list:         typing.List[ControlProperties],
                modify_uuid_list:           typing.List[str]):
        """ Constructor

        Args:
            coord_input:               coordinate input
            pyp_path:                  path of the pyp file
            global_str_table_service:  global string table service for default strings
            build_ele_list:            list with the building elements containing parameter properties
            build_ele_composite:       building element composite
            control_props_list:        control properties list
            modify_uuid_list:          UUIDs of the existing elements in the modification mode
        """


    def modify_element_property(self,
                                page : int,
                                name : str,
                                value: typing.Any) -> None:
        """ Called after each property modification (e.g., in the property palette
        or by using a handle)

        Args:
            page:   index of the page, beginning with 0
            name:   name of the modified property
            value:  new property value
        """

    def on_control_event(self,
                         event_id: int) -> None:
        """ Called when an event is triggered by a palette control (ex. button)

        Args:
            event_id:   id of the triggered event, defined in the tag `<EventId>`
        """

    def on_mouse_leave(self) -> None:
        """ Called when the mouse leaves the viewport window """

    def on_preview_draw(self) -> None:
        """ Called when an input in the dialog line is done (e.g. input of a coordinate)."""

    def on_value_input_control_enter(self) -> bool:
        """Called when enter key is pressed inside the value input control

            Returns:
                True/False for success.
        """

        return True


    def process_mouse_msg(self,
                          mouse_msg:    int,
                          pnt:          AllplanGeometry.Point2D,
                          msg_info:     AllplanIFWInput.AddMsgInfo) -> bool:
        """ Called on each mouse message. A mouse message can be mouse movement, pressing a mouse button
        or releasing it.

        Args:
            mouse_msg:  the mouse message (e.g. 512 - mouse movement)
            pnt:        the input point in view coordinates
            msg_info:   additional message info.

        Returns:
            True/False for success.
        """

        return True

    def execute_save_favorite(self,
                              file_name: str) -> None:
        """ Called after pressing "Save as a favorite" button in the property palette and
        selecting the location of the favorite file in the file dialog

        Args:
            file_name:  full path and name of the selected favorite file
        """

    def execute_load_favorite(self,
                              file_name: str) -> None:
        """ Called after pressing "Load favorite" button in the property palette and
        selecting the favorite file in the file dialog

        Args:
            file_name:  full path and name of the selected favorite file
        """

    def reset_param_values(self,
                           build_ele_list: typing.List[BuildingElement]) -> None:
        """ Called after pressing "Restore basic setting" button in the property palette

        Args:
            build_ele_list:  list with building elements
        """

    def set_active_palette_page_index(self, active_page_index: int):
        """ Called when changing page in the property palette

        Args:
            active_page_index: index of the active page, starting from 0
        """

    def update_after_favorite_read(self) -> None:
        """ Called after reading the favorite data """

    def on_cancel_function(self) -> bool:
        """ Called when ESC key is pressed.

        Returns:
            True when the PythonPart framework should terminate the PythonPart, False otherwise.
        """

        return True

    def on_cancel_by_menu_function(self) -> None:
        """ Called when the user has started another menu function during the runtime of
        the PythonPart. The PythonPart will always be terminated after this function is completed.
        """

__init__(coord_input, pyp_path, global_str_table_service, build_ele_list, build_ele_composite, control_props_list, modify_uuid_list)

Constructor

Parameters:

Name Type Description Default
coord_input CoordinateInput

coordinate input

required
pyp_path str

path of the pyp file

required
global_str_table_service StringTableService

global string table service for default strings

required
build_ele_list List[BuildingElement]

list with the building elements containing parameter properties

required
build_ele_composite BuildingElementComposite

building element composite

required
control_props_list List[ControlProperties]

control properties list

required
modify_uuid_list List[str]

UUIDs of the existing elements in the modification mode

required
Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def __init__(self,
            coord_input:                AllplanIFWInput.CoordinateInput,
            pyp_path:                   str,
            global_str_table_service:   StringTableService,
            build_ele_list:             typing.List[BuildingElement],
            build_ele_composite:        BuildingElementComposite,
            control_props_list:         typing.List[ControlProperties],
            modify_uuid_list:           typing.List[str]):
    """ Constructor

    Args:
        coord_input:               coordinate input
        pyp_path:                  path of the pyp file
        global_str_table_service:  global string table service for default strings
        build_ele_list:            list with the building elements containing parameter properties
        build_ele_composite:       building element composite
        control_props_list:        control properties list
        modify_uuid_list:          UUIDs of the existing elements in the modification mode
    """

execute_load_favorite(file_name)

Called after pressing "Load favorite" button in the property palette and selecting the favorite file in the file dialog

Parameters:

Name Type Description Default
file_name str

full path and name of the selected favorite file

required
Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def execute_load_favorite(self,
                          file_name: str) -> None:
    """ Called after pressing "Load favorite" button in the property palette and
    selecting the favorite file in the file dialog

    Args:
        file_name:  full path and name of the selected favorite file
    """

execute_save_favorite(file_name)

Called after pressing "Save as a favorite" button in the property palette and selecting the location of the favorite file in the file dialog

Parameters:

Name Type Description Default
file_name str

full path and name of the selected favorite file

required
Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def execute_save_favorite(self,
                          file_name: str) -> None:
    """ Called after pressing "Save as a favorite" button in the property palette and
    selecting the location of the favorite file in the file dialog

    Args:
        file_name:  full path and name of the selected favorite file
    """

modify_element_property(page, name, value)

Called after each property modification (e.g., in the property palette or by using a handle)

Parameters:

Name Type Description Default
page int

index of the page, beginning with 0

required
name str

name of the modified property

required
value Any

new property value

required
Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def modify_element_property(self,
                            page : int,
                            name : str,
                            value: typing.Any) -> None:
    """ Called after each property modification (e.g., in the property palette
    or by using a handle)

    Args:
        page:   index of the page, beginning with 0
        name:   name of the modified property
        value:  new property value
    """

on_cancel_by_menu_function()

Called when the user has started another menu function during the runtime of the PythonPart. The PythonPart will always be terminated after this function is completed.

Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def on_cancel_by_menu_function(self) -> None:
    """ Called when the user has started another menu function during the runtime of
    the PythonPart. The PythonPart will always be terminated after this function is completed.
    """

on_cancel_function()

Called when ESC key is pressed.

Returns:

Type Description
bool

True when the PythonPart framework should terminate the PythonPart, False otherwise.

Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def on_cancel_function(self) -> bool:
    """ Called when ESC key is pressed.

    Returns:
        True when the PythonPart framework should terminate the PythonPart, False otherwise.
    """

    return True

on_control_event(event_id)

Called when an event is triggered by a palette control (ex. button)

Parameters:

Name Type Description Default
event_id int

id of the triggered event, defined in the tag <EventId>

required
Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def on_control_event(self,
                     event_id: int) -> None:
    """ Called when an event is triggered by a palette control (ex. button)

    Args:
        event_id:   id of the triggered event, defined in the tag `<EventId>`
    """

on_mouse_leave()

Called when the mouse leaves the viewport window

Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def on_mouse_leave(self) -> None:
    """ Called when the mouse leaves the viewport window """

on_preview_draw()

Called when an input in the dialog line is done (e.g. input of a coordinate).

Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def on_preview_draw(self) -> None:
    """ Called when an input in the dialog line is done (e.g. input of a coordinate)."""

on_value_input_control_enter()

Called when enter key is pressed inside the value input control

Returns:

Type Description
bool

True/False for success.

Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def on_value_input_control_enter(self) -> bool:
    """Called when enter key is pressed inside the value input control

        Returns:
            True/False for success.
    """

    return True

process_mouse_msg(mouse_msg, pnt, msg_info)

Called on each mouse message. A mouse message can be mouse movement, pressing a mouse button or releasing it.

Parameters:

Name Type Description Default
mouse_msg int

the mouse message (e.g. 512 - mouse movement)

required
pnt Point2D

the input point in view coordinates

required
msg_info AddMsgInfo

additional message info.

required

Returns:

Type Description
bool

True/False for success.

Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def process_mouse_msg(self,
                      mouse_msg:    int,
                      pnt:          AllplanGeometry.Point2D,
                      msg_info:     AllplanIFWInput.AddMsgInfo) -> bool:
    """ Called on each mouse message. A mouse message can be mouse movement, pressing a mouse button
    or releasing it.

    Args:
        mouse_msg:  the mouse message (e.g. 512 - mouse movement)
        pnt:        the input point in view coordinates
        msg_info:   additional message info.

    Returns:
        True/False for success.
    """

    return True

reset_param_values(build_ele_list)

Called after pressing "Restore basic setting" button in the property palette

Parameters:

Name Type Description Default
build_ele_list List[BuildingElement]

list with building elements

required
Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def reset_param_values(self,
                       build_ele_list: typing.List[BuildingElement]) -> None:
    """ Called after pressing "Restore basic setting" button in the property palette

    Args:
        build_ele_list:  list with building elements
    """

set_active_palette_page_index(active_page_index)

Called when changing page in the property palette

Parameters:

Name Type Description Default
active_page_index int

index of the active page, starting from 0

required
Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def set_active_palette_page_index(self, active_page_index: int):
    """ Called when changing page in the property palette

    Args:
        active_page_index: index of the active page, starting from 0
    """

update_after_favorite_read()

Called after reading the favorite data

Source code in src\PythonPartsScriptTemplates\InteractorPythonPart.py
def update_after_favorite_read(self) -> None:
    """ Called after reading the favorite data """

Example

The implementation of the Interactor class in an interactor PythonPart is shown in the example Line2DInteractor located in:

  • ..\etc\PythonPartsExampleScripts\InteractorExamples
  • ..\etc\Examples\PythonParts\InteractorExamples

Inheriting from BaseInteractor

The interactor class can use the class BaseInteractor from the PythonParts framework as a base class. All the member functions required by the PythonParts framework are already implemented in this class as abstract methods. So, when your Interactor is missing one, the method inherited from BaseInteractor will still be available for the framework, avoiding problems by running PythonPart.

from BaseInteractor import BaseInteractor

class Interactor(BaseInteractor):
    ...

Example

An implementation example can be found in Elements3DInteractor located in:

  • ...\etc\PythonPartsExampleScripts\InteractorExamples\Elements3DInteractor.py
  • ...\etc\Examples\PythonParts\InteractorExamples\Elements3DInteractor.pyp

Cancel interactor PythonPart

Cancel by hitting ESC

In a standard PythonPart hitting Esc leads to complete cancel of the PythonPart. In an interactor this can be implemented differently, ex:

  • to cancel the current input step and switch to the next or previous input step
  • to cancel the PythonPart interactor and the PythonPart input completely

The implementation is done in the member function on_cancel_function.

Example

Here is an example of an implementation, where the input is divided into two steps: input of the first and the second point.

def on_cancel_function(self):

    if first_point_input: #(1)!
        palette_service.close_palette()
        return True

    first_point_input = True #(2)!
    coord_input.InitFirstPointInput(AllplanIFW.InputStringConvert("From point"))
    return False #(3)!
  1. When hitting Esc while the first point input is active, the PythonPart should shut down completely...
  2. ... but hitting Esc while the second point input is active should only cancel the second point input and switch to the first point input.
  3. The False value is returned here to communicate to the PythonPart framework, not to terminate the running PythonPart.

Cancel by calling another menu function

An implementation like above can lead to problems, when the user calls another menu function while using PythonPart, without terminating it with Esc first. In this case a complete shutdown of the PythonPart is required, so the framework will call the on_cancel_function as often, as the return value is True. This multiple call may cause the palette to blink and to avoid it, the member function on_cancel_by_menu_function can be implemented:

def on_cancel_by_menu_function(self):

    palette_service.close_palette()
    #(1)
  1. After calling this function and completing the procedures in it, PythonPart framework will always shut the PythonPart down completely, so a return value is not needed.

Example

See the full example in the WallInteractor located in:

  • …\etc\Examples\PythonParts\InteractorExamples\WallInteractor.pyp
  • …\etc\PythonPartsExampleScripts\InteractorExamples\WallInteractor.py