question

Frenk Gao avatar image
0 Likes"
Frenk Gao asked anthony.johnson answered

How to add bound members to a ObjectDataType sub-class manually?

I am trying to Implementing Module DLLs (SDK-Documentation-ModuleDevelopment).

I am trying to add a variable to the object.

But " Add FlexSim Variable" guide in Documentation is still use the "Adding FlexSim Object Variables Wizards" which has been removed. I must add bound members to a ObjectDataType sub-class manually.

So, these in the module sdk Documentation will not help:

1. Go back to Visual Studio. Right-click on
the testmodule project in the Solution Explorer, and choose Add > New
Item...
2. Choose "Add FlexSim Variable"
and hit "Add"
3. For Class, enter
"MyTaskExecuter". For Variable Name, enter "xonly". Check
the box for "Number Data." Hit "Finish." Note - Sometimes
this wizard can be finnicky and give you errors when you add variables. I think
it may have to do with intelli-sense not being up-to-date, so sometimes if you
just close and re-open, or just compile, it fixes itself.

Could you update the Documentation show me the C++ rockie how to add FlexSim Variable?

FlexSim 16.0.9
module sdk
5 |100000

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

anthony.johnson avatar image
0 Likes"
anthony.johnson answered

Sorry for the out-of-date Module SDK documentation. Mischa's answer still works, but in my own development I have dispensed with the "node_v_" usage that binds using bindobjectclassvariable() and instead use native types using bindVariable(). The class code that uses this would be something like the following:

class MyTaskExecuter : public TaskExecuter 
{
public:
   virtual void bindVariables(void);
   // ...   
   double myDoubleVariable;
   NodeRef myNodeRef;
   treenode myVariableNode;
   ByteBlock myByteBlock;
   NodeListArray<OtherClassType>::StoredAttCouplingType objectList;
};
Then the implementation of bindVariables() would be:
#include "MyTaskExecuter.h"
void MyTaskExecuter::bindVariables()
{
	__super::bindVariables();
	bindVariable(myDoubleVariable);
	bindVariable(myNodeRef);
	bindVariable(myObjRef);
	bindVariable(myVariableNode);
	bindVariable(myByteBlock);
	bindVariable(objectList);
}

The advantage of doing it this way is that the syntax is simpler to learn, and you can access values directly instead of using the older mechanism where you have to do a #define v_varName to get/set the value of a variable node. The bindVariable() macro can take what's demonstrated above, namely doubles, NodeRefs, treenodes (this binds the same as the old way, i.e. the class member points to a node in the object's variables tree), ByteBlocks (for string data), and NodeListArrays (those are bound the same as treenodes).

5 |100000

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

Mischa Spelt avatar image
3 Likes"
Mischa Spelt answered Mischa Spelt commented

Hi Frenk, here are the steps required to bind a variable in the class to a FlexSim variable:

1. In your class, create a variable and declare an override of the bindVariables function:

class MyObject :
  public FlexSimObject /* or BasicFR, or ... */ 
{
public:
   virtual void bindVariables(void);
   // ...   
   treenode node_v_myVariable;
};

2. In the C++ file, call bindobjectclassvariable from the bindvariables function:

void MyObject::bindVariables()
{
  FlexSimObject::bindVariables(); // Call base class function
  bindobjectclassvariable( this->holder, &node_v_myVariable, "myvariableintree", "MyObject" );
}

where

  • this->holder refers to the treenode associated to this object
  • node_v_myVariable refers to the class field (we use node_v_.. by convention for all such fields)
  • "myvariableintree" is the name of the node in the tree - node_v_myVariable will be associated to the treenode at MyObject>variables/myvariableintree, creating the node at this point if it does not exist
  • "MyObject" refers to the class by name as you have also spelled it in your createodtderivative.
· 2
5 |100000

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

Frenk Gao avatar image Frenk Gao commented ·

Thank you for your reply!

I try it in my module project:

MyTaskExecuter.cpp:

#include "MyTaskExecuter.h"
void MyTaskExecuter::bindVariables()
{
	TaskExecuter::bindVariables();
	bindobjectclassvariable(this->holder, &node_v_xonly, "node_v_xonly", "MyTaskExecuter");
}
	double MyTaskExecuter::beginOffset(double endspeed, treenode item)
{
	if (xonly){
		offsetloc[1] = 0;
		offsetloc[2] = 0;
	}
	return beginOffsetDefault(endspeed, item);
}

MyTaskExecuter.h:

#pragma once
#include "FlexsimDefs.h"
#include "allobjects.h"
class MyTaskExecuter : public TaskExecuter
{
	public:
	virtual void bindVariables(void);
	virtual double beginOffset(double endspeed, treenode item);
	treenode node_v_xonly;
};

But it throw an error:

Error error C2065: 'xonly' : undeclared identifier

How can I use the value of the xonly node that I just added to MyObject?

And I look into MyTaskExecuter>variables, there is a node named "node_v_xonly" not the "xonly". Is there anything wrong?

0 Likes 0 ·
xonly.png (2.5 KiB)
Mischa Spelt avatar image Mischa Spelt Frenk Gao commented ·

No, this is exactly what you asked for when you specified "node_v_xonly" as the third argument to bindobjectclassvariable

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

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