This page has been translated automatically.
视频教程
界面
要领
高级
实用建议
专业(SIM)
UnigineEditor
界面概述
资源工作流程
版本控制
设置和首选项
项目开发
调整节点参数
Setting Up Materials
设置属性
照明
Sandworm
使用编辑器工具执行特定任务
如何擴展編輯器功能
嵌入式节点类型
Nodes
Objects
Effects
Decals
光源
Geodetics
World Nodes
Sound Objects
Pathfinding Objects
Players
编程
搭建开发环境
使用范例
C++
C#
UnigineScript
UUSL (Unified UNIGINE Shader Language)
Plugins
File Formats
材质和着色器
Rebuilding the Engine Tools
GUI
VR Development
双精度坐标
应用程序接口
Animations-Related Classes
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes
VR-Related Classes
创建内容
内容优化
材质
Material Nodes Library
Miscellaneous
Input
Math
Matrix
Textures
Art Samples
Tutorials

事件处理回调

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.回调是一个函数包装,表示指向静态和成员函数的指针,这些函数预期在特定时刻使用指定参数执行。回调可以作为参数传递给其他函数。

注意
Callbacks are guaranteed to be reentrant and provide safe multi-threaded execution.确保回调是可重入的,并提供安全的多线程执行。

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()函数:

源代码 (C++)
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:创建对当前类或另一个类的成员函数的回调,如下所示:

源代码 (C++)
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..类用于创建带有固定数量参数的回调。根据参数的数量,应使用相应的类。在这种情况下,您应该提供模板参数:

源代码 (C++)
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 use overloaded functions and methods as callbacks, provide the template parameters:
MakeCallback< Class, ReturnType, Callback Parameters Types >
要使用重载函数和方法作为回调,请提供模板形参:
MakeCallback< Class, ReturnType, Callback Parameters Types >

源代码 (C++)
void ThisClass::callback_method()
{
	/* .. */
}

void ThisClass::callback_method(WidgetPtr w, WidgetPtr w2, int i)
{
	/* .. */
}

CallbackBase *callback = MakeCallback<ThisClass, void, WidgetPtr, WidgetPtr, int>(this, &ThisClass::callback_method);

To raise a custom callback, the run() function of one of the CallbackBase classes is used.要引发自定义回调,请使用CallbackBase..类的run()函数。

源代码 (C++)
// 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表达式用于回调:

源代码 (C++)
// 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
#ifndef __APP_WORLD_LOGIC_H__
#define __APP_WORLD_LOGIC_H__

#include <UnigineLogic.h>
#include <UnigineStreams.h>
#include <UnigineCallback.h>

using namespace Unigine;
using namespace Math;

class AppWorldLogic: public Unigine::WorldLogic
{

public:

	int init() override;

	int update() override;
	int postUpdate() override;
	int updatePhysics() override;

	int shutdown() override;

	int save(const Unigine::StreamPtr &stream) override;
	int restore(const Unigine::StreamPtr &stream) override;
};

#endif // __APP_WORLD_LOGIC_H__
AppWorldLogic.cpp
#include "AppWorldLogic.h"

class SomeClass
{
public:
	// a member function to be called on the 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, 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 parameters. The predefined ones will be ignored
		callback2->run(351, 153);
		// run the callback with only 1 parameter.
		// the second predefined parameter will be used as the second argument
		callback2->run(118);
	}
};

// a callback function to be called on the 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();
	// call the SomeClass member function
	some->create_callbacks();

	Log::message("Create a callback in the other instance\n");
	// use the callback function of the SomeClass 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::update()
{

	return 1;
}

int AppWorldLogic::postUpdate()
{
	return 1;
}

int AppWorldLogic::updatePhysics()
{
	return 1;
}

int AppWorldLogic::shutdown()
{
	return 1;
}

int AppWorldLogic::save(const Unigine::StreamPtr &stream)
{
	UNIGINE_UNUSED(stream);
	return 1;
}

int AppWorldLogic::restore(const Unigine::StreamPtr &stream)
{
	UNIGINE_UNUSED(stream);
	return 1;
}

实际使用#

回调在事件处理中被广泛使用。许多Unigine API成员具有几个预定义的事件,在某些情况下可以使用回调来处理。

扳机#

触发器用于检测节点位置或状态的变化。 Unigine提供了三种类型的内置触发器:

这是一个简单的WorldTrigger用法示例:

源代码 (C++)
WorldTriggerPtr trigger;
void *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;
}

要删除回调,请使用以下代码:

源代码 (C++)
// 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 ).

小部件#

小部件基类Widget允许注册GUI类中定义的事件的回调。下面的示例演示如何创建WidgetButton并注册CLICKED事件的回调函数:

源代码 (C++)
// event handler function
int AppWorldLogic::onButtonClicked()
{
	Log::message("\nThe widget button has been clicked\n");

	return 1;
}

int AppWorldLogic::init()
{

	// get a pointer to the system GUI
	GuiPtr gui = Gui::getCurrent();
	// create a button widget and set its caption
	WidgetButtonPtr widget_button = WidgetButton::create(gui, "Press me");
	// set a tooltip
	widget_button->setToolTip("Click this button");
	// rearrange a button size
	widget_button->arrange();
	// set a button position
	widget_button->setPosition(10, 10);
	// set the onButtonClicked function to handle the CLICKED event
	widget_button->addCallback(Gui::CLICKED, MakeCallback(this, &AppWorldLogic::onButtonClicked));
	// add the created button widget to the system GUI
	gui->addChild(widget_button, Gui::ALIGN_OVERLAP | Gui::ALIGN_FIXED);

	return 1;
}
也可以看看
  • C++ API示例 ( <UnigineSDK>/source/csharp/samples/Api/Widgets/WidgetCallbacks ).
  • 创建用户界面教程。

物理#

您可以跟踪与物理学相关的实体关节的某些事件:

下面的示例显示了为BodyRigid注册回调并根据其状态更改网格颜色的方法:

源代码 (C++)
// set the node's albedo color to red on the 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 the 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
	ObjectMeshStaticPtr meshStatic = ObjectMeshStatic::create("core/meshes/box.mesh");
	meshStatic->setPosition(Vec3(0, 0, 5.0f));
	// add a rigid body to the box
	BodyRigidPtr body = BodyRigid::create(meshStatic);
	// 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;
}
注意
基于物理的回调在主菜单中执行,因为它们主要用于创建,销毁或修改其他对象。
也可以看看

位于<UnigineSDK>/source/samples/Api/Physics/BodyCallbacks文件夹中的C ++ API示例。

物产#

回调函数可用于确定在添加或删除节点和曲面属性以及交换节点属性时要执行的操作。这是一个演示如何通过回调跟踪添加节点属性的示例:

源代码 (C++)
void AppWorldLogic::node_property_added(NodePtr node, PropertyPtr property)
{
	Log::message("Property \"%s\" was added to the node named \"%s\".\n", property->getName(), node->getName());
}

int AppWorldLogic::init()
{

	NodeDummyPtr node = NodeDummy::create();

	// search for a property named "new_property_0"
	PropertyPtr property = Properties::findProperty("new_property_0");

	// set the callback function on adding a node property
	node->addCallback(Node::CALLBACK_PROPERTY_NODE_ADD, MakeCallback(this, &AppWorldLogic::node_property_added));

	// add the property named "new_property_0" to the node
	node->addProperty("new_property_0");

	return 1;
}

您可以添加回调以跟踪对属性及其参数所做的任何更改并执行某些操作。

下面的示例演示如何添加回调以跟踪属性参数的更改,并报告属性的名称和更改后的参数(假设我们有一个名为my_prop的手动属性,其整数参数为my_int_param)。

源代码 (C++)
void AppWorldLogic::parameter_changed(PropertyPtr property, int num)
{
	Log::message("Parameter \"%s\" of the property \"%s\" has changed its value.\n", property->getParameterPtr(num)->getName(), property->getName());	
}

int AppWorldLogic::init()
{

	// set the callback function on parameter change
	property->addCallback(Property::CALLBACK_PARAMETER_CHANGED, MakeCallback(this, &AppWorldLogic::parameter_changed));

	// change the value of the "my_int_param" parameter
	property->getParameterPtr("my_int_param")->setValueInt(3);

	return 1;
}

您还可以将回调添加到Properties管理器,以跟踪对任何属性所做的任何更改并执行某些操作:

源代码 (C++)
void AppWorldLogic::property_removed(PropertyPtr property)
{
	Log::message("Property \"%s\" was removed.\n", property->getName());
}

int AppWorldLogic::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_REMOVED, MakeCallback(this, &AppWorldLogic::property_removed));

	// remove the property named "new_property_1"
	Properties::removeProperty(Properties::findProperty("new_property_1")->getGUID());

	return 1;
}
最新更新: 2023-12-19
Build: ()