Learning VSL Through Examples
VSL Behavior Tasks
Creating Tasks
Tasks are owned by Behaviors. To create a Task, you must therefore first create a Behavior, or open an already exisiting Behavior in the Behavior Editor. Within the Behavior you can then create a Task:
- In the “Tasks” sections of the Behavior Editor, double-click on the keyword “New Task”.
- Select “VSL task” from the “New” dialog.
- Enter a name for your Task and press “Ok”.
The new VSL Task opens in the VSL Editor for editing.
Executing Tasks
Tasks are executed automatically by the 3DVIA Studio Behavioral Engine when they are activated. Tasks are activated by default when the owner Behavior is activated. However, you can have an e.g. VSL Function activate a Task, provided the Behavior is itself active.
See the Behavioral Engine documentation for additional informations.
Examples
The following example illustrates a Task named “Move” owned by a Behavior named “KeyboardMove”. The main action is described in the “Execute” function, where keyboard inputs are used to move a targeted 3D object.
//Task declaration
task KeyboardMove::Move
{
Target {
vkNode3DPtr node3D;
};
pLocal {
};
// hen task starts
void OnStart() { }
//When task stops
void OnStop() { }
//Check Keyboard status and apply movement
bool Execute(const vkTaskContext& iCtx)
{
vkIODeviceManager& im = vkIODeviceManager::Instance(kMainCtx);
vkKeyboardPtr keyboard = im.Keyboard();
vkVec3 translation;
vkVec3 rotationAxis;
translation.x = 0;
translation.y = 0;
translation.z = speed;
rotationAxis.x = 0;
rotationAxis.y = 1.0f;
rotationAxis.z = 0;
if (keyboard.IsKeyPressed(vkKeyboard::eLeft)) {
node3D.Rotate(rotationAxis,-0.05f,node3D);
}
if (keyboard.IsKeyPressed(vkKeyboard::eRight)) {
node3D.Rotate(rotationAxis,0.05f,node3D);
}
if (keyboard.IsKeyPressed(vkKeyboard::eUp)) {
node3D.Translate(translation,node3D);
}
if (keyboard.IsKeyPressed(vkKeyboard::eDown)) {
translation.z = -translation.z;
node3D.Translate(translation,node3D);
}
return true;
}
};
VSL Behavior Functions
Creating Functions
Functions, like Tasks, are owned by Behaviors. To create a Function, you must therefore first create a Behavior, or open an already exisiting Behavior in the Behavior Editor. Within the Behavior you can then create a Function:
- In the “Functions” sections of the Behavior Editor, double-click on the keyword “New Function ”.
- Select “VSL function ” from the “New” dialog.
- Enter a name for your Function and press “Ok”.
The new VSL Function opens in the VSL Editor for editing.
Using Functions
Behavior Functions can be used in the Schematic Editor or when programming in VSL.
In the Schematic Editor, VSL Behavior Functions can be used just like Building Blocks: when dragged and dropped from the Types library to the Schematic, the Function is encapsulated as a Building Block and can thus be used just like a Building Block.
When used in the VSL Editor, VSL Functions can be called with the regular function call statement.
Example
The following VSL Behavior Function creates dynamic actors based on a set of given parameters. The function, which is called “CreateActor”, is owned by a Behavior named “ActorFactory”.
//Parameters
//iActorName : the actor name
//iActorTemplate : the actor template
vkActor* ActorFactory::CreateActor(const vkString& iActorName, vkTemplatePtr& iActorTemplate) {
//Retrieve the stage
vkStage* currentStage = GetStage();
//Create a new actor
vkActor* newActor = currentStage.CreateDynamicActor(iActorName, iActorTemplate);
//Return the created actor
return newActor;
}
VSL Building Blocks
Creating Building Blocks
- Locate the Building Block library.
- Select a folder to contain the Building Block (a Project/User folder or subfolder).
- Right-click on the folder contents (bottom pane) and select “New Building Block”.
Using Building Blocks
User-created VSL Building Blocks can be used in the Schematic Editor like preset Building Blocks: just drag and drop them to the Schematic Editor to instantiate.
Example
The following VSL Building Block changes the orientation of a 3D object according to a set of given parameters.
//Definition of the building block LookAt
buildingblock LookAt
{
pIn {
vkNode3DPtr iNode;
vkVec3 iPosition;
vkNode3DPtr iReferential;
float iAttenuation;
};
void Execute(const BBContext& iContext)
{
float deltaTime = iContext.GetClock().deltaTime;
if (!iNode || (deltaTime == 0.0)) {
return;
}
vkPoint targetPos;
vkPoint localTargetPos;
vkNode3DPtr referential = pin.iReferential;
if (referential) {
referential.GetWorldTransform().Multiply(targetPos, pin.iPosition);
}
else {
return;
}
vkTransform& worldTrans = pin.iNode.GetWorldTransform();
worldTrans.InvertMultiply(localTargetPos, targetPos);
vkVec3 alignTest = localTargetPos;
localTargetPos.z = 0.0;
if (localTargetPos.SquareMagnitude() <= 0.0000001) {
return;
}
vkQuat oldOrientation;
worldTrans.ComputeRotation(oldOrientation);
vkVector direction = targetPos – worldTrans.GetPosition();
vkVector worldUp(0.0, 1.0, 0.0);
vkQuat newOrientation(direction, worldUp);
float attenuation = pin.iAttenuation;
attenuation /= deltaTime * 0.1f;
float speed = 1.0;
newOrientation.Slerp(speed, oldOrientation, newOrientation);
pin.iNode.SetWorldOrientation(newOrientation);
}
};
VSL Asset Processors
Creating Asset Processors
- Open the Asset Processors library.
- Select a folder to contain the Asset Processor (a Project/User folder or subfolder).
- Right-click on the folder’s Asset Processor list (right-hand pane) and select “New Script Processor”.
Using Asset Processors
VSL Asset Processors are used to process Assets, during the Build Process, using User-specified operations.
The structure of an Asset Processor is just like that of a Building Block (see VSL Script Types for more information):
- The main function is the “Execute” function.
- There are three Execute signature levels: whereas the top one is called, the others are masked automatically.
The three different signature levels as listed below, in order:
- void Execute(const vkURI& iAsset, const vkURI& oAsset, vkBuildContext* iContext) //top level
- void Execute(vkAsset* iSource, vkAsset* oDest, vkBuildContext* iContext)
- void Execute(vkResource* iResource, vkBuildContext* iContext)
- Input parameters can be declared inside the “pIn” structure.
Asset Processors instance Input parameters can be configured from the Build Explorer‘s Build Info View. - It is also possible to add a “pLocal” structure to handle local parameters (just like the members of a class).
Example
The following Asset Processor resizes a bitmap image.
//Definition of the processor ImageResizerProcessor
proccessor ImageResizerProcessor
{
/*
pLocal plocal {
};
*/
pIn {
vkString resourceFilter;
int32 width = 16;
int32 height = 16;
int32 ratio = 0;
};
void Execute(vkResource* iResource, vkBuildContext* iContext)
{
//Get source image
vkImagePtr image = iResource;
if (!image) {
return;
}
//Compute new dimentions
uint32 newWidth = width;
uint32 newHeight = height;
if(ratio) {
newWidth = (uint32) (image.GetSize().x * (newWidth/100.0f));
newHeight = (uint32) (image.GetSize().y * (newHeight/100.0f));
}
//some info logging
vkString msg = "resizing image to ";
msg << newWidth << "x" << newHeight;
iContext.LogInfo(msg);
//Resize image
error err = image.Resize(newWidth, newHeight, image.GetDepth());
if (err != errOk) {
iContext.LogError("cannot resize the image");
return;
}
}
};
