Event Handling Callbacks
Callback is a function wrapper representing a pointer to static and member functions which are expected to be executed with specified parameters at a certain moment. A callback can be passed as an argument to a function.
Unigine C# API lets you specify function delegates as callbacks to handle events.
void node_property_added(Node n, Property property)
{
/* .. */
}
node.AddCallback(Node.CALLBACK_PROPERTY_NODE_ADD, node_property_added);
You can also use lambda expressions for the same event handling purpose:
widget_button.AddCallback(Gui.CLICKED, () => Log.Message("Button pressed\n"));
Practical Use#
Callbacks are widely used in event handling. A number of Unigine API members have several predefined events which can be handled by using callbacks in certain cases.
Triggers#
Triggers are used to detect changes in nodes position or state. Unigine offers three types of built-in triggers:
- NodeTrigger fires callbacks when the trigger node is enabled or the trigger node position has changed.
- WorldTrigger fires callbacks when any node (collider or not) gets inside or outside of it.
- PhysicalTrigger fires callbacks when physical objects get inside or outside of it.
Here is a simple WorldTrigger usage example:
using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;
#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
using Vec3 = Unigine.vec3;
using Vec4 = Unigine.vec4;
using Mat4 = Unigine.mat4;
#endif
[Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
public class Callbacks : Component
{
// implement the enter callback
void enter_callback(Node node)
{
Log.Message("\nA node named {0} has entered the trigger\n", node.Name);
}
// implement the leave callback
void leave_callback(Node node)
{
Log.Message("\nA node named {0} has left the trigger\n", node.Name);
}
WorldTrigger trigger;
System.IntPtr enter_callback_id;
private void Init()
{
// create a world trigger
trigger = new WorldTrigger(new vec3(3.0f));
// add the enter callback to be fired when a node enters the world trigger
// and keep its id to be used to remove the callback when necessary
enter_callback_id = trigger.AddEnterCallback(enter_callback);
// add the leave callback to be fired when a node leaves the world trigger
trigger.AddLeaveCallback(leave_callback);
}
private void Update()
{
}
private void Shutdown()
{
}
}
To remove the callbacks use the following code:
// remove the callback by using its id
trigger.RemoveEnterCallback(enter_callback_id);
// clear all leave callbacks
trigger.ClearLeaveCallbacks();
See Also
- C# API samples on NodeTrigger, WorldTrigger and PhysicalTrigger located in the <UnigineSDK>/source/csharp/samples/Api/Nodes folder.
Widgets#
The widgets base class Widget allows registering callbacks for events defined in the GUI class. The following example shows how to create a WidgetButton and register a callback function for the CLICKED event:
using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;
#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
using Vec3 = Unigine.vec3;
using Vec4 = Unigine.vec4;
using Mat4 = Unigine.mat4;
#endif
[Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
public class Callbacks : Component
{
private void Init()
{
// get the system GUI
Gui gui = Gui.GetCurrent();
// create a button widget and set its caption
WidgetButton widget_button = new WidgetButton(gui, "Press me");
// rearrange a button size
widget_button.Arrange();
// set a button position
widget_button.SetPosition(10,10);
// set a lambda function to handle the CLICKED event
widget_button.AddCallback(Gui.CALLBACK_INDEX.CLICKED, () => Log.Message("Button pressed\n"));
// add the created button widget to the system GUI
gui.AddChild(widget_button, Gui.ALIGN_OVERLAP | Gui.ALIGN_FIXED);
}
private void Update()
{
}
private void Shutdown()
{
}
}
See Also
C# API samples located in the <UnigineSDK>/source/csharp/samples/Api/Widgets folder.
Physics#
You can track certain events of the physics-related Bodies and Joints:
- Body.AddFrozenCallback() to track an event when a body freezes.
- Body.AddPositionCallback() to track an event when a body changes its position.
- Body.AddContactEnterCallback() to track an event when a contact emerges (body starts touching another body or collidable surface).
- Body.AddContactLeaveCallback() to track an event when a contact ends (body stops touching another body or collidable surface).
- Body.AddContactsCallback() to get all contacts of the body including new ones (enter) and the ending ones (leave). Leave contacts are removed after the callback execution stage, so this is the only point where you can still get them.
- Joint.AddBrokenCallback() to track an event when a joint breaks.
The following sample shows the way of registering callbacks for a BodyRigid and change the color of a mesh depending on its state:
using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;
#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
using Vec3 = Unigine.vec3;
using Vec4 = Unigine.vec4;
using Mat4 = Unigine.mat4;
#endif
[Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
public class Callbacks : Component
{
private void Init()
{
// create a box
ObjectMeshStatic meshStatic = new ObjectMeshStatic("core/meshes/box.mesh");
meshStatic.Position = new Vec3(0, 0, 5.0f);
// add a rigid body to the box
BodyRigid body = new BodyRigid(meshStatic);
// register callbacks for events by using lambda functions
body.AddFrozenCallback(b => b.Object.SetMaterialParameterFloat4("albedo_color", new vec4(1.0f, 0.0f, 0.0f, 1.0f), 0));
body.AddPositionCallback(b => b.Object.SetMaterialParameterFloat4("albedo_color", new vec4(0.0f, 0.0f, 1.0f, 1.0f), 0));
body.AddContactEnterCallback((b, num) => b.Object.SetMaterialParameterFloat4("albedo_color", new vec4(1.0f, 1.0f, 0.0f, 1.0f), 0));
// add a shape to the body
ShapeBox shape = new ShapeBox(body, new vec3(1.0f));
}
private void Update()
{
}
private void Shutdown()
{
}
}
See Also
A C# API sample located in the <UnigineSDK>/source/csharp/samples/Api/Physics/BodyCallbacks folder.
Properties#
Callback functions can be used to determine actions to be performed when adding or removing node and surface properties as well as when swapping node properties. Here is an example demonstrating how to track adding a node property via callbacks:
using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;
#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
using Vec3 = Unigine.vec3;
using Vec4 = Unigine.vec4;
using Mat4 = Unigine.mat4;
#endif
[Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
public class Callbacks : Component
{
void node_property_added(Node n, Property property)
{
Log.Message("Property \"{0}\" was added to the node named \"{1}\".\n", property.Name, n.Name);
}
private void Init()
{
NodeDummy node = new NodeDummy();
// search for a property named "new_property_0"
Property property = Properties.FindProperty("new_property_0");
// set the callback function on adding a node property
Node.AddCallback(Node.CALLBACK_INDEX.PROPERTY_NODE_ADD, node_property_added);
// add the property named "new_property_0" to the node
node.AddProperty("new_property_0");
}
private void Update()
{
}
private void Shutdown()
{
}
}
You can add callbacks to track any changes made to a property and its parameters and perform certain actions.
The example below shows how to add a callback to track changes of property parameters and report the name of the property and the changed parameter.
using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;
#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
using Vec3 = Unigine.vec3;
using Vec4 = Unigine.vec4;
using Mat4 = Unigine.mat4;
#endif
[Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
public class Callbacks : Component
{
void parameter_changed(Property property, int num)
{
Log.Message("Parameter \"{0}\" of the property \"{1}\" has changed its value.\n", property.GetParameterPtr(num).Name, property.Name);
}
private void Init()
{
// set the callback function on parameter change
property.AddCallback(Property.CALLBACK_INDEX.PARAMETER_CHANGED, parameter_changed);
// change the value of the "my_int_param" parameter
property.GetParameterPtr("my_int_param").SetValue(3);
}
private void Update()
{
}
private void Shutdown()
{
}
}
You can also add callbacks to the Properties manager to track any changes made to any property and perform certain actions:
using System;
using System.Collections;
using System.Collections.Generic;
using Unigine;
#if UNIGINE_DOUBLE
using Vec3 = Unigine.dvec3;
using Vec4 = Unigine.dvec4;
using Mat4 = Unigine.dmat4;
#else
using Vec3 = Unigine.vec3;
using Vec4 = Unigine.vec4;
using Mat4 = Unigine.mat4;
#endif
[Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
public class Callbacks : Component
{
public void property_removed(Property property)
{
Log.Message("Property \"{0}\" was removed.\n", property.Name);
}
private void Init()
{
// inherit a new property named "new_property_1" from the base property "surface_base"
Properties.FindManualProperty("surface_base").Inherit("new_property_1");
// set the callback function on property removal
Properties.AddCallback(Properties.CALLBACK_INDEX.REMOVED, property_removed);
// remove the property named "new_property_1"
Properties.RemoveProperty(Properties.FindProperty("new_property_1").GUID);
}
private void Update()
{
}
private void Shutdown()
{
}
}
See Also#
These are not all usage examples of event handling callbacks. The following list contains more API members supporting event handling:
- UserInterface - for handling events from widgets created by loading a UI file.
- Render - callback functions can be used to get access to buffers and matrices at intermediate stages of the rendering sequence.
- Console supports adding a callback function that will be executed when a text is output to the console.
- EditorLogic - a set of editor callback functions can be overridden for certain purposes.
- ComponentBase - there may be performed certain actions on destroying a component.
- AsyncQueue - сallback functions can be used to determine actions to be performed when certain resources are loaded.
- WorldSplineGraph provides a set of callbacks for handling actions on editing points and segments.
- Viewport - callback functions can be used to get access to buffers and matrices at intermediate stages of the rendering sequence.