事件处理回调
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. Callback can be passed as an argument to other function.回调是一个函数包装,表示指向静态和成员函数的指针,这些函数预期在特定时刻使用指定参数执行。回调可以作为参数传递给其他函数。
In Unigine C++ API the CallbackBase is the base class to represent callbacks with variable number of arguments from 0 to 5. To create a callback the MakeCallback() function is used:在Unigine C ++ API中,CallbackBase是表示具有从0到5的可变数量参数的回调的基类。要创建回调,请使用MakeCallback()函数:
void callback_function() {
/* .. */
}
CallbackBase *callback = MakeCallback(callback_function);
A callback to a member function of either the current class or another is created as follows:创建对当前类或另一个类的成员函数的回调,如下所示:
void ThisClass::callback_function() {
/* .. */
}
/* .. */
// the first argument is an instance of a class, the second one is the pointer to a member function
CallbackBase *callback = MakeCallback(this, &ThisClass::callback_function);
The CallbackBase.. classes are used to create a callback with fixed number of arguments. Depending on the number of arguments the corresponding class should be used. In this case you should provide template arguments: CallbackBase..类用于创建带有固定数量参数的回调。根据参数的数量,应使用相应的类。在这种情况下,您应该提供模板参数:
void ThisClass::callback_function(NodePtr, int) {
/* .. */
}
// create a callback with no predefined parameters
CallbackBase2<NodePtr, int> *callback = MakeCallback(this, &ThisClass::callback_function);
// create a callback with predefined parameters
CallbackBase2<NodePtr, int> *callback2 = MakeCallback(this, &ThisClass::callback_function, NodeDummy::create()->getNode(), 1);
// create a callback with parameters from lambda
CallbackBase2<NodePtr, int> *callback = MakeCallback([](NodePtr node, int value) { /* .. */ });
// create a callback with parameters from generic lambda
CallbackBase2<NodePtr, int> *callback = MakeCallback([](auto node, auto value) { /* .. */ });
To raise a custom callback the run() function of the CallbackBase.. class is used.要引发自定义回调,请使用CallbackBase..类的run()函数。
// run the callback with no parameters or with default predefined parameters
callback->run();
// run the callback with the specified parameters
callback->run(node, 2);
You can also use lambda expressions for callbacks:您还可以将lambda表达式用于回调:
// create a callback from lambda
int value = 5;
CallbackBase* callback = MakeCallback([value](){ /* .. */ });
// or std function
std::function<void()> callable_obj = [value]() { /* .. */ };
CallbackBase* callback = MakeCallback(callable_obj);
// or any other type of callable
struct Callable
{
void operator()() const { /* .. */ }
int value;
} callable_obj = { /* .. */ };
CallbackBase* callback = MakeCallback(callable_obj);
Usage Example使用范例#
The following section contains the complete source code of a simple callback usage example.以下部分包含一个简单的回调用法示例的完整源代码。
AppWorldLogic.h AppWorldLogic.h
#include <UnigineLogic.h>
#include <UnigineStreams.>
#include <UnigineCallback.h>
using namespace Unigine;
class AppWorldLogic : public WorldLogic {
public:
AppWorldLogic();
virtual ~AppWorldLogic();
virtual int init();
virtual int update();
virtual int postUpdate();
virtual int updatePhysics();
virtual int shutdown();
}
#endif // __APP_WORLD_LOGIC_H__
AppWorldLogic.cpp AppWorldLogic.cpp
#include "AppWorldLogic.h"
AppWorldLogic::AppWorldLogic()
{
}
AppWorldLogic::~AppWorldLogic()
{
}
int AppWorldLogic::update()
{
return 1;
}
class SomeClass
{
public:
// a member function to be called on action
void callback_method(int a, int b)
{
Log::message("\tcallback_method has been called %d %d\n", a, b);
}
void create_callbacks()
{
Log::message("create a callback with no predefined parameters\n");
CallbackBase * callback = MakeCallback(this, &SomeClass::callback_method);
// run the callback with two parameters
callback->run(73, 37);
// run the callback with no parameters.
// if the callback function has arguments like in this case, this will lead to unsafe behaviour
callback->run();
Log::message("create a callback with predefined parameters\n");
CallbackBase * callback2 = MakeCallback(this, &SomeClass::callback_method, 1, 2);
// run the callback with no parameters. In this case the predefined parameters will be used
callback2->run();
// run the callback with new parameters. The predefined ones will be ignored
callback2->run(351, 153);
// run the callback with only one first parameter.
// the second predefined parameter will be used as the second argument
callback2->run(118);
}
};
// a callback function to be called on action
void callback_function(int a, int b)
{
Log::message("\tcallback_function has been called %d %d\n", a, b);
}
int AppWorldLogic::init()
{
SomeClass * some = new SomeClass();
a->create_callbacks();
Log::message("create a callback in other instance\n");
// use a member function of another class to create a callback
CallbackBase * callback3 = MakeCallback(some, &SomeClass::callback_method, 5, 25);
callback3->run();
Log::message("create callback functions\n");
CallbackBase * callback4 = MakeCallback(&callback_function);
callback4->run(20,70);
CallbackBase * callback5 = MakeCallback(&callback_function , 50, 25);
callback5->run();
return 1;
}
int AppWorldLogic::postUpdate()
{
return 1;
}
int AppWorldLogic::updatePhysics()
{
return 1;
}
int AppWorldLogic::shutdown()
{
return 1;
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.回调在事件处理中被广泛使用。许多Unigine API成员具有几个预定义的事件,在某些情况下可以使用回调来处理。
Triggers扳机#
Triggers are used to detect changes in nodes position or state. Unigine offers three types of built-in triggers:触发器用于检测节点位置或状态的变化。 Unigine提供了三种类型的内置触发器:
- NodeTrigger fires callbacks when the trigger node is enabled or the trigger node position has changed. NodeTrigger在触发节点启用或触发节点 position 更改时触发回调。
- WorldTrigger fires callbacks when any node (collider or not) gets inside or outside of it. WorldTrigger在任何节点(是否有对撞机)获取其 inside 或 outside 时触发回调。
- PhysicalTrigger fires callbacks when physical objects get inside or outside of it. PhysicalTrigger在物理对象获取 inside 或 outside 时触发回调。
Here is a simple WorldTrigger usage example:这是一个简单的WorldTrigger用法示例:
WorldTriggerPtr trigger;
int enter_callback_id;
// implement the enter callback
void AppWorldLogic::enter_callback(NodePtr node){
Log::message("\nA node named %s has entered the trigger\n", node->getName());
}
// implement the leave callback
void AppWorldLogic::leave_callback(NodePtr node){
Log::message("\nA node named %s has left the trigger\n", node->getName());
}
int AppWorldLogic::init() {
// create a world trigger node
trigger = WorldTrigger::create(Math::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(MakeCallback(this, &AppWorldLogic::enter_callback));
// add the leave callback to be fired when a node leaves the world trigger
trigger->addLeaveCallback(MakeCallback(this, &AppWorldLogic::leave_callback));
return 1;
}
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();
也可以看看
- C++ API示例 ( <UnigineSDK>/source/samples/Api/Nodes/NodeTrigger ).
- C++ API示例 ( <UnigineSDK>/source/samples/Api/Nodes/WorldTrigger ).
- C++ API示例 ( <UnigineSDK>/source/samples/Api/Nodes/PhysicalTrigger ).
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:小部件基类Widget允许注册GUI类中定义的事件的回调。下面的示例演示如何创建WidgetButton并注册CLICKED事件的回调函数:
/* .. */
// event handler function
int onButtonClicked()
{
/* .. */
return 1;
}
/* .. */
// getting a pointer to the system GUI
GuiPtr gui = Gui::get();
// creating a button widget and setting its caption
WidgetButtonPtr widget_button = WidgetButton::create(gui, "Press me");
// setting a tooltip
widget_button->setToolTip("Click this button");
// rearranging button size
widget_button->arrange();
// setting button position
widget_button->setPosition(10, 10);
// setting onButtonClicked function to handle CLICKED event
widget_button->addCallback(Gui::CLICKED, MakeCallback(onButtonClicked));
// adding the created button widget to the system GUI
gui->addChild(widget_button, Gui::ALIGN_OVERLAP | Gui::ALIGN_FIXED);
也可以看看
- A C++ API sample ( <UnigineSDK>/source/csharp/samples/Api/Widgets/WidgetCallbacks ). C++ API示例 ( <UnigineSDK>/source/csharp/samples/Api/Widgets/WidgetCallbacks ).
- An example of Creating User Interface. 创建用户界面教程。
Physics物理#
You can track certain events of the physics-related Bodies and Joints:您可以跟踪与物理学相关的实体和关节的某些事件:
- Body::addFrozenCallback() to track an event when a body freezes. Body::addFrozenCallback()跟踪物体冻结时的事件。
- Body::addPositionCallback() to track an event when a body changes its position. Body::addPositionCallback()用于在主体更改其位置时跟踪事件。
- Body::addContactEnterCallback() to track an event when a contact emerges (body starts touching another body or collidable surface). Body::addContactEnterCallback()跟踪出现接触时的事件(身体开始接触另一个身体或可碰撞的表面)。
- Body::addContactLeaveCallback() to track an event when a contact ends (body stops touching another body or collidable surface). Body::addContactLeaveCallback()用来跟踪接触结束时的事件(身体停止接触另一个身体或可碰撞的表面)。
- 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. Body::addContactsCallback()获取身体的所有接触,包括新接触(输入)和结束接触(离开)。离开联系人在回调执行阶段之后被删除,因此这是仍然可以获取它们的唯一点。
- Joint::addBrokenCallback() to track an event when a joint breaks. Joint::addBrokenCallback()跟踪关节断开时的事件。
The following sample shows the way of registering callbacks for a BodyRigid and change the color of a mesh depending on its state:下面的示例显示了为BodyRigid注册回调并根据其状态更改网格颜色的方法:
/* .. */
// set the node's albedo color to red on freezing event
int AppWorldLogic::frozen_callback(BodyPtr body)
{
body->getObject()->setMaterialParameterFloat4("albedo_color", vec4(1.0f, 0.0f, 0.0f, 1.0f), 0);
return 1;
}
// set the node's albedo color to blue on position change event
int AppWorldLogic::position_callback(BodyPtr body)
{
body->getObject()->setMaterialParameterFloat4("albedo_color", vec4(0.0f, 0.0f, 1.0f, 1.0f), 0);
return 1;
}
// set the node's albedo color to yellow on each contact
int AppWorldLogic::contact_enter_callback(BodyPtr body, int num)
{
body->getObject()->setMaterialParameterFloat4("albedo_color", vec4(1.0f, 1.0f, 0.0f, 1.0f), 0);
return 1;
}
int AppWorldLogic::init() {
// create a box
MeshPtr mesh = Mesh::create();
mesh->addBoxSurface("box", vec3(1.0f));
ObjectMeshStaticPtr node = ObjectMeshStatic::create(mesh);
node->setMaterial("mesh_base", "*");
node->setPosition(Vec3(0, 0, 5.0f));
// add a rigid body to the box
BodyRigidPtr body = BodyRigid::create(node);
// register callbacks for events
body->addFrozenCallback(MakeCallback(this, &AppWorldLogic::frozen_callback));
body->addPositionCallback(MakeCallback(this, &AppWorldLogic::position_callback));
body->addContactEnterCallback(MakeCallback(this, &AppWorldLogic::contact_enter_callback));
// add a shape to the body
ShapeBoxPtr shape = ShapeBox::create(body, vec3(1.0f));
return 1;
}
/* .. */
也可以看看
A C++ API sample located in the <UnigineSDK>/source/samples/Api/Physics/BodyCallbacks folder.位于<UnigineSDK>/source/samples/Api/Physics/BodyCallbacks文件夹中的C ++ API示例。
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:回调函数可用于确定在添加或删除节点和曲面属性以及交换节点属性时要执行的操作。这是一个演示如何通过回调跟踪添加节点属性的示例:
NodePtr node;
void node_property_added(NodePtr node, PropertyPtr property)
{
Log::message("Property \"%s\" was added to the node named \"%s\".\n", property->getName(), node->getName());
// ...
}
// somewhere in the code
// inheriting a new property named "my_prop" from the base property "node_base"
Properties::findManualProperty("node_base")->inherit("my_prop");
// setting our callback function on adding a node property
node->addCallback(Node::CALLBACK_PROPERTY_NODE_ADD, MakeCallback(node_property_added));
// adding the property named "my_prop" to the node
node->addProperty("my_prop");
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 (suppose we have a manual property named my_prop with an integer parameter named my_int_param).下面的示例演示如何添加回调以跟踪属性参数的更改,并报告属性的名称和更改后的参数(假设我们有一个名为my_prop的手动属性,其整数参数为my_int_param)。
void parameter_changed(PropertyPtr property, int num)
{
Log::message("Parameter \"%s\" of the property \"%s\" has changed its value.\n", property->getParameterName(num), property->getName());
// ...
}
// somewhere in the code
// getting a manual property named "my_prop" via the Property Manager
PropertyPtr property = Properties::findManualProperty("my_prop");
// setting our callback function on parameter change
property->addCallback(Property::CALLBACK_PARAMETER_CHANGED, MakeCallback(parameter_changed));
// changing the value of the "my_int_param" parameter
property->setParameterInt(property->findParameter("my_int_param"), 3);
You can also add callbacks to the Properties manager to track any changes made to any property and perform certain actions:您还可以将回调添加到Properties管理器,以跟踪对任何属性所做的任何更改并执行某些操作:
void property_removed(PropertyPtr property)
{
Log::message("Property \"%s\" was removed.\n", property->getName());
// ...
}
// somewhere in the code
// inheriting a new property named "my_prop" from the base property "surface_base"
PropertyPtr property = Properties::findManualProperty("surface_base")->inherit("my_prop");
// setting our callback function on property removal
Properties::addCallback(Property::CALLBACK_REMOVED, MakeCallback(property_removed));
// removing the property named "my_prop"
Properties::removeProperty(Properties::findProperty("my_prop")->getGUID());
See Also也可以看看#
These are not all usage examples of event handling callbacks. The following list contains more API members supporting event handling:这些并不是事件处理回调的所有用法示例。以下列表包含更多支持事件处理的API成员:
- UserInterface - for handling events from widgets created by loading a UI file. UserInterface-用于处理通过加载UI文件创建的小部件中的事件。
- Render - callback functions can be used to get access to buffers and matrices at intermediate stages of the rendering sequence. Render-回调函数可用于在渲染序列的中间阶段访问缓冲区和矩阵。
- Console supports adding a callback function that will be executed when a text is output to the console. Console支持添加在文本输出到控制台时将执行的回调函数。
- EditorLogic - a set of editor callback functions can be overridden for certain purposes. EditorLogic-出于某些目的,可以覆盖一组编辑器回调函数。
- ComponentBase - there may be performed certain actions on destroying a component. ComponentBase-在销毁组件时可能会执行某些操作。
- AsyncQueue - сallback functions can be used to determine actions to be performed when certain resources are loaded. AsyncQueue-所有版本的函数都可以用来确定在加载某些资源时要执行的操作。
- WorldSplineGraph provides a set of callbacks for handling actions on editing points and segments. WorldSplineGraph提供了一组回调,用于处理对编辑点和线段的操作。
- Viewport - callback functions can be used to get access to buffers and matrices at intermediate stages of the rendering sequence. Viewport-回调函数可用于在渲染序列的中间阶段访问缓冲区和矩阵。
Plugins:插件: