icon

Script Object with multiple Interactors

Tagy:
  • Script Objects

Hi there,

I am currently facing the following problem and was hoping to get some support from the community.

Most of the Object script examples I have seen implement an interactor once. For instance

def start_input(self):
"""Start the element selection"""

self.script_object_interactor = SingleElementSelectInteractor(self.first_selection_result,
ele_filter= valid_element_types,
prompt_msg "Select Element A")

Normally, the script would follow to def start_next_input, where I could have

def start_next_input(self):
"""Start the element selection"""

self.script_object_interactor = MultiElementSelectInteractor(self.second_selection_result,
ele_filter= valid_element_types,
prompt_msg "Select Element B & C")

However, if I want to have a start_third-input as follows, to simply trigger def execute(self)

def start_third_input(self):
"""Start the element selection"""

self.script_object_interactor = None

How can I implement this? As described above, it simply doesn't, as start_third_input(self) is not expected in BaseScriptObject.

Any suggestions here? Perhaps I am approaching the problem in the wrong way.

Looking forward to hearing from the community.

Cheers

Show most helpful answer Hide most helpful answer

Hi,

The switching between input steps must all be done in the start_next_input(). Only the first input step should be started in the start_input(). The implementation should involve keeping track of what input step is currently active. You can achieve it by defining an instance attribute "current_input_step" in your ScriptObject class and changing it whenever a new input step is started.

begin with defining the enumeration class representing your input steps:

class InputStep(IntEnum):
    Undefined = 0
    First  = 1
    Second = 2
    Third  = 3
    Fourth = 4
    Fifth  = 5

Second, define the instance attributes in your ScriptObject class for storing the input results:

def __init__(self,build_ele, script_object_data):

    super().__init__(script_object_data)

    # set initial values
    self.build_ele              = build_ele
    self.first_input_result     = MultiElementSelectInteractorResult()
    self.second_input_result    = PointInteractorResult()
    self.third_input_result     = SingleElementSelectResult()
    self.fourth_input_result    = PointInteractorResult()
    self.fifth_input_result     = SingleElementSelectResult()

    self.current_input_step     = InputStep.Undefined    # here the attribute for keeping track of the current input step

Start the first input step:

def start_input(self):
    self.script_object_interactor = MultiElementSelectInteractor(
        self.first_input_result,
        prompt_msg="First, select some elements")
    self.current_input_step = InputStep.First     # keep track of the current input step!

Switch the input step, depending on what is the current one. Everything in the start_next_input():

def start_next_input(self):
    """Start the next input step"""

    if self.current_input_step == InputStep.First:
        # when there is a valid result for the first input step, start the second input step
        self.script_object_interactor = PointInteractor(
            self.second_input_result, False,
            request_text="Now, select a point")
        self.current_input_step = InputStep.Second
        return

    if self.current_input_step == InputStep.Second:
        # when there is a valid result for the second input step, start the third input step
        self.script_object_interactor = SingleElementSelectInteractor(
            self.third_input_result,
            prompt_msg="Next, select an element")
        self.current_input_step = InputStep.Third
        return
    ...

Find the complete script attached.

Cheers,
Bart

Přílohy (1)

Type: text/plain
Staženo 142
Size: 4,90 KiB

Hi,

the ScriptObject can work as a "State Machine".

You need to add a "state" member variable to your script. Depending on this state
you can start the next interactor in "start_next_input". With an initial value of "xxx" it looks like

match self.state:
    case xxx:
        self.script_object_interactor = ...

        self.state = yyy

    case yyy:
        self.script_object_interactor = ...

        self.state = zzz

    case zzz:
        ...

Best regards
Horst

Hi,

The switching between input steps must all be done in the start_next_input(). Only the first input step should be started in the start_input(). The implementation should involve keeping track of what input step is currently active. You can achieve it by defining an instance attribute "current_input_step" in your ScriptObject class and changing it whenever a new input step is started.

begin with defining the enumeration class representing your input steps:

class InputStep(IntEnum):
    Undefined = 0
    First  = 1
    Second = 2
    Third  = 3
    Fourth = 4
    Fifth  = 5

Second, define the instance attributes in your ScriptObject class for storing the input results:

def __init__(self,build_ele, script_object_data):

    super().__init__(script_object_data)

    # set initial values
    self.build_ele              = build_ele
    self.first_input_result     = MultiElementSelectInteractorResult()
    self.second_input_result    = PointInteractorResult()
    self.third_input_result     = SingleElementSelectResult()
    self.fourth_input_result    = PointInteractorResult()
    self.fifth_input_result     = SingleElementSelectResult()

    self.current_input_step     = InputStep.Undefined    # here the attribute for keeping track of the current input step

Start the first input step:

def start_input(self):
    self.script_object_interactor = MultiElementSelectInteractor(
        self.first_input_result,
        prompt_msg="First, select some elements")
    self.current_input_step = InputStep.First     # keep track of the current input step!

Switch the input step, depending on what is the current one. Everything in the start_next_input():

def start_next_input(self):
    """Start the next input step"""

    if self.current_input_step == InputStep.First:
        # when there is a valid result for the first input step, start the second input step
        self.script_object_interactor = PointInteractor(
            self.second_input_result, False,
            request_text="Now, select a point")
        self.current_input_step = InputStep.Second
        return

    if self.current_input_step == InputStep.Second:
        # when there is a valid result for the second input step, start the third input step
        self.script_object_interactor = SingleElementSelectInteractor(
            self.third_input_result,
            prompt_msg="Next, select an element")
        self.current_input_step = InputStep.Third
        return
    ...

Find the complete script attached.

Cheers,
Bart

Přílohy (1)

Type: text/plain
Staženo 142
Size: 4,90 KiB

Citoval bmarciniec
Hi,
The switching between input steps must all be done in the start_next_input(). Only the first input step should be started in the start_input(). The implementation should involve keeping track of what input step is currently active. You can achieve it by defining an instance attribute "current_input_step" in your ScriptObject class and changing it whenever a new input step is started.
begin with defining the enumeration class representing your input steps:

class InputStep(IntEnum): Undefined = 0 First = 1 Second = 2 Third = 3 Fourth = 4 Fifth = 5Second, define the instance attributes in your ScriptObject class for storing the input results:

def __init__(self,build_ele, script_object_data): super().__init__(script_object_data) # set initial values self.build_ele = build_ele self.first_input_result = MultiElementSelectInteractorResult() self.second_input_result = PointInteractorResult() self.third_input_result = SingleElementSelectResult() self.fourth_input_result = PointInteractorResult() self.fifth_input_result = SingleElementSelectResult() self.current_input_step = InputStep.Undefined # here the attribute for keeping track of the current input step
Start the first input step:

def start_input(self): self.script_object_interactor = MultiElementSelectInteractor( self.first_input_result, prompt_msg="First, select some elements") self.current_input_step = InputStep.First # keep track of the current input step!
Switch the input step, depending on what is the current one. Everything in the start_next_input():

def start_next_input(self): """Start the next input step""" if self.current_input_step == InputStep.First: # when there is a valid result for the first input step, start the second input step self.script_object_interactor = PointInteractor( self.second_input_result, False, request_text="Now, select a point") self.current_input_step = InputStep.Second return if self.current_input_step == InputStep.Second: # when there is a valid result for the second input step, start the third input step self.script_object_interactor = SingleElementSelectInteractor( self.third_input_result, prompt_msg="Next, select an element") self.current_input_step = InputStep.Third return ...
Find the complete script attached.
Cheers,

Bart

Hi Bart,

thank for your scirpt.

I want to select muiltiple objects in each state after finish the select i would press Esc for moving to next state.
For e.x :

State 1 : Select object : 1 ,2 ,3 ,4 .v.v.v n . Then confirm select and save the object to a list.
State 2 : Select object : 1 ,2 ,3 ,4 .v.v.v n . Then confirm select and save the object to a list.
State 3 : Select object : 1 ,2 ,3 ,4 .v.v.v n . Then confirm select and save the object to a list.

After that I have list of [State 1], [State 2], [State 3]