script_struct¶
- script_struct … script_struct¶
script_struct Name script_variables ... end_script_variables script ... ... end_script uncloneable end_script_struct
Warning
Prior to WSF 2.0, script_struct instances were created with the struct.New method and the variables and methods in the instance had to be accessed via the ‘->’ operator. Unfortunately that implementation was not type-safe and lead to many hard-to-find errors. What is being described here is the new syntax. The old syntax should not be used unless you need the struct on the fly capabilities.
Overview¶
The ‘script_struct’ block defines an new ‘class’ that behaves much like any of the built-in classes (e.g.: WsfGeoPoint). Instances of the class can be used as arguments to or returned by script methods and be used as template types in the Array, Map and Set containers. A script_struct block that defines a new class is valid only as a top-level command (that is, they cannot be inside platforms, processors or any other block). In addition, a script_struct class must be defined before it is used. The following section demonstrates the creation and use of a struct.
Commands¶
- uncloneable¶
Specify that instances of this script_struct cannot be cloned.
Note
script_struct
s are cloneable by default.
script_struct example¶
script_struct Car
script_variables
WsfGeoPoint position = { };
Vec3 velocity = { };
string color = "red";
end_script_variables
script void Honk()
writeln(color, " car honks");
end_script
end_script_struct
on_initialize
# Create a new instance of the struct
Car car = Car();
# Clone the new instance
Car clone = Car(car);
# Assign some values.
car.color = "blue";
car.position.Set(39, -90, 125.0);
car.velocity.Set(20, 0, 0);
# Call a script
car.Honk();
# Print the contents of the struct
writeln(car);
end_on_initialize
output:
blue car honks
struct({"position": 39:00:00.0n 90:00:00.0w 125, "velocity": (20, 0, 0), "color": blue})
Another test that shows a struct being used as a container type
script_struct Cat
script_variables
string name = "unknown";
int livesLeft = 9;
end_script_variables
script int UseA_Life()
if (livesLeft > 0) livesLeft -= 1;
if (livesLeft <= 0)
{
writeln("So sorry, ", name, " has used all of its lives");
}
return livesLeft;
end_script
end_script_struct
on_initialize
Cat cat1 = { };
cat1.name = "fluffy";
Cat cat2 = { };
cat2.name = "morris";
cat1.UseA_Life();
cat1.UseA_Life();
cat1.UseA_Life();
cat1.UseA_Life();
cat1.UseA_Life();
cat1.UseA_Life();
cat1.UseA_Life();
cat1.UseA_Life();
int i1 = cat1.UseA_Life();
writeln(cat1.name, " has ", cat1.livesLeft, " lives left");
if (i1 != 0)
{
writeln("-FAIL- fluffy should have 0 lives left, but has ", i1);
}
int i2 = cat2.UseA_Life();
writeln(cat2.name, " has ", cat2.livesLeft, " lives left");
if (i2 != 8)
{
writeln("-FAIL- morris should have 8 lives left, but has ", i1);
}
# Some simple tests of Cats as container members. Not a full-blown test,
# but at least it checks compilation.
Array<Cat> catArray = { };
catArray.PushBack(cat1);
catArray.PushBack(cat2);
writeln("CatArray: ", catArray);
writeln("foreach over catArray");
foreach (Cat cat in catArray)
{
writeln(" cat=", cat);
}
Map<string, Cat> catMap = { cat1.name : cat1, cat2.name : cat2 };
writeln("Cat Map: ", catMap);
writeln("foreach over catMap");
foreach (string name : Cat cat in catMap)
{
writeln(" ", name, " ", cat);
}
Set<Cat> catSet = { cat1, cat2 };
writeln("Cat Set: ", catSet);
writeln("foreach over catSet");
foreach (Cat cat in catSet)
{
writeln(" cat=", cat);
}
end_on_initialize
output:
So sorry, fluffy has used all of its lives
fluffy has 0 lives left
morris has 8 lives left
CatArray: {struct({"name": fluffy, "livesLeft": 0}), struct({"name": morris, "livesLeft": 8})}
foreach over catArray
cat=struct({"name": fluffy, "livesLeft": 0})
cat=struct({"name": morris, "livesLeft": 8})
Cat Map: {fluffy : struct({"name": fluffy, "livesLeft": 0}), morris : struct({"name": morris, "livesLeft": 8})}
foreach over catMap
fluffy struct({"name": fluffy, "livesLeft": 0})
morris struct({"name": morris, "livesLeft": 8})
Cat Set: {struct({"name": fluffy, "livesLeft": 0}), struct({"name": morris, "livesLeft": 8})}
foreach over catSet
cat=struct({"name": fluffy, "livesLeft": 0})
cat=struct({"name": morris, "livesLeft": 8})
struct on the fly¶
Warning
This example uses the old syntax for creating an instance of a struct and accessing the variables and methods. This is not type-safe and should be avoided unless you need to dynamically add new variables to the struct.
# A struct is best used with the basic types (int, double, bool, string). However, # it can be used to contain the data of complex types (WsfPlatform, WsfGeoPoint, etc) # script_variables WsfGeoPoint point1 = WsfGeoPoint(); point1.Set(0,0,1); end_script_variables platform test WSF_PLATFORM on_initialize2 # Empty structs can be created and used like this: struct container = struct(); container->a = 1.0; # Gets recognized as a double container->b = 5.0; # Gets recognized as a double container->c = "test1"; # Gets recognized as a string container->d = 10; # Gets recognized as an int container->e = false; # Boolean equal to false container->x = (string)"test2"; # type cast to a string (overkill) container->y = (double)10; # force a type cast number without a decimal point to a double container->z = (string)"500"; # type cast to a string (overkill) container->p1 = point1; # bring in an external complex type variable container->p2 = WsfGeoPoint(); # Create an empty GeoPoint complex type container->p3 = WsfGeoPoint.Construct(0,0,0); # Create a GeoPoint that has an LLA writeln(container); # The whole container can be passed around as one object... # THE ONLY PERIOD "." METHODS AVAILABLE WHEN USING THE "->" OPERATOR ON COMPLEX TYPES # ARE ToString(), IsValid(), and IsNull(). writeln("p1 in container is ", container->p1.ToString() ); writeln("p2 in container is ", container->p2.ToString() ); writeln("p3 in container is ", container->p3.ToString() ); # The following illustrates how to update objects in a container. # If a struct variable is a complex type, a typical period "." method CANNOT # be used directly on the variable because the type is not known using the "->" operator. container->a = container->a + 1; # Add 1 to var a. Since it is not using a ".", it will work. #container->p2 = container->p2.Set(0,0,2); # Set p2 to a new LLA #WRONG - THIS LINE WILL FAIL #Use one of these: ((WsfGeoPoint)container->p2).Set(0,0,2); # Cast to WsfGeoPoint and call Set(); OR: WsfGeoPoint p2 = container->p2; # Get value and call Set() p2.Set(0,0,2); #container->p3.Set(0,0,3); # Set p3 to a new LLA # WRONG - THIS LINE WILL FAIL ((WsfGeoPoint)container->p3).Set(0,0,3); # Cast to WsfGeoPoint and call Set(); OR: WsfGeoPoint p3 = container->p3; p3.Set(0,0,3); writeln("p2 in container after updating is ", container->p2.ToString() ); writeln("p3 in container after updating is ", container->p3.ToString() ); end_on_initialize2 end_platform
output:
struct({"p1": WsfGeoPoint, "z": 500, "e": 0, "d": 10, "a": 1, "p3": WsfGeoPoint, "y": 10, "c": test1, "p2":
WsfGeoPoint, "x": test2, "b": 5})
p1 in container is 00:00:00.0n 00:00:00.0e 1
p2 in container is 00:00:00.0n 00:00:00.0e 0
p3 in container is 00:00:00.0n 00:00:00.0e 0
p2 in container after updating is 00:00:00.0n 00:00:00.0e 2
p3 in container after updating is 00:00:00.0n 00:00:00.0e 3
Using a map containing a struct¶
Warning
This example uses the old syntax for creating an instance of a struct and accessing the variables and methods. This is not type-safe and should be avoided unless you need to dynamically add new variables to the struct.
platform TEST_VEHICLE WSF_PLATFORM
add processor script_proc WSF_SCRIPT_PROCESSOR
script_variables
struct myContainer = struct(); # Make a struct named myContainer
myContainer->counter = 1; # One field being a counter
myContainer->JustAColor = "Gray"; # Another field with a string
myContainer->JustANumber = 0; # Any number
myContainer->MaxNumber = 50; # A maximum number
end_script_variables
update_interval 1 sec
on_update
extern struct myContainer; # Bring in the struct "myContainer"
myContainer->AirplaneType = "F-18"; # Add a member to myContainer"
Map<int, struct> MyMapWithStruct = Map<int, struct>(); # Create a map of a struct
MyMapWithStruct[0] = myContainer; # Set index 0 of the map to the contents of myContainer
foreach (int aKey : struct aData in MyMapWithStruct)
{
writeln("key, data ", aKey, ", ", aData);
myContainer->JustANumber = MATH.Roll(1,10);
if(myContainer->counter >= 25) myContainer->JustAColor = "Blue";
if(myContainer->counter >= (myContainer->MaxNumber - 5) ) WsfSimulation.Terminate();
myContainer->counter = myContainer->counter + 1;
}
end_on_update
end_processor
end_platform
See Also¶
struct - struct script class