question

Mischa Spelt avatar image
2 Likes"
Mischa Spelt asked Ryan Clark commented

Calling updatelocations in pre draw crashes FlexSim

I wanted to write a PreDraw trigger which keeps a traveller on the floor:

if( current.location.z != 0 )
{
  updatelocations( current );
  /**/current.location.z = 0/**/;
}

Previously I had to make sure to call updatelocations first to apply any kinematics since the last draw.

This still works in 21.1 but as of 21.2 (including versions of 2022) there seems to be a change where this causes a stack overflow. When I put the debugger on the updatelocations line and Step Into, I recursively end up in the same OnPreDraw trigger.

TestUpdateLocations.fsm

I see why OnPreDraw first does updatelocations but I don't understand why calling updatelocations explicitly calls OnPreDraw again. Is this a bug?

FlexSim 21.2.0
onpredrawstack overflowupdatelocations
· 1
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Ryan Clark avatar image Ryan Clark commented ·

Hi @Mischa Spelt, was Phil BoBo's answer helpful? If so, please click the "Accept" button at the bottom of their answer. Or if you still have questions, add a comment and we'll continue the conversation.

If we haven't heard back from you within 3 business days we'll auto-accept an answer, but you can always unaccept and comment back to reopen your question.

0 Likes 0 ·

1 Answer

Phil BoBo avatar image
3 Likes"
Phil BoBo answered Phil BoBo edited

This isn't a bug. This is by design.

Starting with 21.2, updatelocations() calls the object's OnPreDraw trigger so that code in the OnPreDraw that updates an object's location will fire when updatelocations() is called. For an example, see Anthony's KIVA model:

Dev Talk: Kiva System Modeling - YouTube

Example Kiva System Model - FlexSim Community

Previously, if you were updating kinematics (or otherwise setting the object's location) within your OnPreDraw trigger, then that only fired when drawing, not when calling updatelocations(). Now your kinematics will be updated appropriately during updatelocations() instead of only getting updated if the view repaints.

The onPreDraw() method of most object classes already calls the updateLocations() method on that object. That's primarily what the onPreDraw() method is for. You shouldn't need to call it yourself from your OnPreDraw trigger. For example, see MAIN:/project/library/fixedresources/Processor>behaviour/cppfunctions/onPreDraw(treenode view)

(The first line of that code is updateLocations().)

If you want to explicitly call updatelocations() as part of your OnPreDraw trigger so that it executes before the rest of the code in your trigger instead of afterwards, then you can return 1 from the OnPreDraw trigger to prevent updatelocations() from then calling updateLocations() after calling your OnPreDraw trigger code. See MAIN:/project/exec/globals/cppfunctions/updatelocations(treenode object)

Object current = ownerobject(c);
treenode view = param(1);

if (current.updating?)
    return 0;
current.updating = 1;
updatelocations(current);
current.updating = 0;

current.location.z = 0;
return 1;
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.