This page has been translated automatically.
视频教程
界面
要领
高级
实用建议
基础
专业(SIM)
UnigineEditor
界面概述
资源工作流程
Version Control
设置和首选项
项目开发
调整节点参数
Setting Up Materials
设置属性
照明
Sandworm
使用编辑器工具执行特定任务
如何擴展編輯器功能
嵌入式节点类型
Nodes
Objects
Effects
Decals
光源
Geodetics
World Nodes
Sound Objects
Pathfinding Objects
Players
编程
搭建开发环境
使用范例
C++
C#
UnigineScript
统一的Unigine着色器语言 UUSL (Unified UNIGINE Shader Language)
Plugins
File Formats
材质和着色器
Rebuilding the Engine Tools
GUI
双精度坐标
应用程序接口
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

事件处理

When writing your application logic, one of the biggest challenges you're likely to face is connecting the various changing elements in a way that works. For example, making a character move, jump, or adding up the score can be relatively easy to do on its own. But connecting all things that happen in your game or application without making it confusing to work with can be very challenging.在编写应用程序逻辑时,您可能面临的最大挑战之一是以一种有效的方式连接各种变化的元素。例如,让角色移动、跳跃或增加分数可以相对容易地自行完成。但是,将游戏或应用中发生的所有内容连接起来而又不让人感到困惑是非常具有挑战性的。

The Event System enables you to create application logic that is executed when an event is triggered during the application execution. It allows objects to subscribe one or more of their own functions to a subject's event. Then, when the subject triggers the event, the objects' functions are called in response. Such functions are also known as event handlers. 事件系统使您能够创建在应用程序执行期间触发事件时执行的应用程序逻辑。它允许对象将自己的一个或多个函数订阅到主题的事件。然后,当主题触发事件时,将调用对象的函数作为响应。这样的函数也称为事件处理程序

The Event System features the following:事件系统的特点如下:

  • Strict type checking for signatures: you can see how many and which exactly arguments an event handler function requires.签名的严格类型检查:您可以看到事件处理程序函数需要多少参数以及确切需要哪些参数。
  • Compile-time checking: it ensures that argument types match event types, preventing runtime errors.编译时检查:确保参数类型匹配事件类型,防止运行时错误。
  • Simple subscription/unsubscription to events with lambda functions with no need to perform internal type conversions.使用lambda函数简单订阅/取消订阅事件,无需执行内部类型转换。
  • Automatic event unsubscription.事件自动退订
  • Temporary event deactivation: particular events can be temporarily disabled to perform specific actions without triggering them. 临时事件停用:可以暂时禁用特定事件以执行特定操作而不触发它们。
  • Batch management: you can unsubscribe from several subscriptions in a single function call.批处理管理:您可以在单个函数调用中取消订阅多个订阅。

Events
事件#

An event is represented by the abstract Event class. It serves as an interface for interaction with the event. Typically, you get this interface via a reference as Event<args...>, where args represents a list of arguments the event will pass to a handler function.事件由抽象Event类表示。它充当与事件交互的接口。通常,通过引用Event<args...>获得该接口,其中args表示事件将传递给处理程序函数的参数列表。

For example, Body::getEventPosition() returns the event with the following signature:例如, Body::getEventPosition()返回带有以下签名的事件:

源代码 (C++)
Event<const Ptr<Body>&>

It means the handler function must receive an argument of the same type when connected with the event.这意味着处理程序函数在与事件连接时必须接收相同类型的参数。

Emulating Events
模拟事件#

Sometimes, it is necessary to emulate events. For custom events, you can use the EventInvoker::run() function that receives the same arguments as the event and invokes its handler functions.有时,模拟事件是必要的。对于自定义事件,可以使用EventInvoker::run()函数,该函数接收与事件相同的参数并调用其处理程序函数。

The following example shows how to create your event and then run it when necessary:下面的例子展示了如何创建事件并在必要时运行它:

源代码 (C++)
class MyEventClass
{
public:

	Event<int> &getEvent() { return event; }

	void runEvent()
	{
		num_runs++;
		event.run(num_runs);
	}

private:

	int num_runs = 0;
	EventInvoker<int> event;
};

int main()
{
	MyEventClass my_class;
	EventConnections e_conn;

	my_class.getEvent().connect(
		e_conn,
		[](int n)
		{
			printf("n = %d\n", n);
		}
	);

	my_class.runEvent();
	my_class.runEvent();

	return 0;
}

The existing events that are implemented for built-in objects and available through API can be emulated using the corresponding runEvent*() methods (without having to use EventInvoker::run()). For example, to emulate the Show event for a widget, call Widget::runEventShow().为内置对象实现并通过API可用的现有事件可以使用相应的runEvent*()方法进行模拟(而不必使用EventInvoker::run())。例如,要模拟小部件Show事件,调用Widget::runEventShow()

源代码 (C++)
widget->runEventShow();

Event Handlers
事件处理程序#

The event handler functions can receive no more than 5 arguments.事件处理函数接收的参数不能超过5个

In addition, the Event System performs strict type checking for handler function signatures: you can subscribe to the event only if the types of the function arguments match the event types. For example, in the case of the event with a single int argument, you are only able to link it with a handler that also accepts a single integer argument. Even if the types can be implicitly converted (as in the example), subscribing is not permitted.此外,事件系统对处理程序函数签名执行严格的类型检查:只有当函数参数的类型与事件类型匹配时,您才能订阅事件。例如,对于具有单个int参数的事件,您只能将其与也接受单个整数参数的处理程序链接。即使类型可以隐式转换(如示例中所示),也不允许订阅。

源代码 (C++)
Event<int> event;	// event sugnature
void on_event(int a);	// types match, subscription is allowed
void on_event(long a);	// type mismatch, no subscription

This restriction also applies to the &, const, and const& modifiers. For instance, when the event type is a user class with no modifiers:这个限制也适用于&, constconst&修饰符。例如,当事件类型是没有修饰符的用户类时:

源代码 (C++)
Event<MyClass> event;
void on_event(MyClass a);			// types match, subscription is allowed
void on_event(MyClass a&);		// type mismatch
void on_event(const MyClass a&);// type mismatch

Discarding Arguments
丢弃的论点#

In most cases, not all arguments passed to the handler function by the event are necessary. So, events allow for discarding unnecessary arguments when functions subscribe to them. You can only discard one argument at a time, starting with the last one. For example, the following handler functions can subscribe to the event:在大多数情况下,并非事件传递给处理程序函数的所有参数都是必需的。因此,当函数订阅事件时,事件允许丢弃不必要的参数。一次只能放弃一个参数,从最后一个开始。例如,以下处理函数可以订阅事件:

源代码 (C++)
// the event
Event<int, float, const char *, vec3, const MyClass &> event;

// the event handlers with discarded arguments
on_event(int a, float b, const char *s, vec3 v, const MyClass &c);
on_event(int a, float b, const char *s, vec3 v);
on_event(int a, float b, const char *s);
on_event(int a, float b);
on_event(int a);
on_event();

Receiving Additional Arguments
接收附加参数#

To receive an additional user argument in the handler function, you need to add the required argument to the end of the handler arguments list and pass its value to the connect() function.要在处理程序函数中接收额外的用户参数,需要将所需的参数添加到处理程序参数列表的末尾,并将其值传递给connect()函数。

注意
There is a limitation: using references as additional arguments is not allowed. This restriction is associated with the fact that a copy of the argument is made in the CallbackBase class.有一个限制:不允许使用引用作为附加参数。这个限制与在 CallbackBase 类中创建参数副本的事实有关。
源代码 (C++)
class UserClass
{
	{ /* ... */ }
};

Event<int, float> event;

void on_event_0(int a, float b, int my_var) { /* ... */ }

void on_event_1(int a, float b, UserClass c) { /* ... */ }

void on_event_2(int a, float b, UserClass *c_ptr) { /* ... */ }

void on_event(float f, const char *str) { /* ... */ }

UserClass user_class;

int main()
{
	// pass the value of the additional "my_var" argument to the handler function
	event.connect(on_event_0, 33);
	// pass the value of the additional "c" argument to the handler function
	event.connect(on_event_1, user_class);
	// pass the value of the additional "c_ptr" argument to the handler function
	event.connect(on_event_2, &user_class);
	// discard the int and float handler arguments, add the custom float and const char* and pass them to connect()
	event.connect(on_event, 33.3f, "test");

	return 0;
}

Subscribing to Events
订阅事件#

For convenience, the Event System provides the EventConnection and EventConnections classes that allow simple event subscription/unsubscription. Let's go through them in detail.为方便起见,事件系统提供了EventConnectionEventConnections类,它们允许简单的事件订阅/取消订阅。让我们详细介绍一下。

Single Subscription with EventConnection
带有EventConnection的单订阅#

The EventConnection class keeps a connection between an event and its handler. For example, the connection between the event and the free handler function can be set as follows:EventConnection类保持事件与其处理程序之间的连接。例如,事件与自由处理函数之间的连接可以设置如下:

源代码 (C++)
EventConnection connection;

// a handler function
void on_event()
{
	Log::message("\Handling the event\n");
}

void init()
{
	//connect the handler function with the event by using EventConnection
	getSomeEvent().connect(connection, this, on_event);

}

You can temporarily turn the event off to perform specific actions without triggering it.您可以暂时关闭事件以执行特定的操作而不触发它。

源代码 (C++)
// disable the event
getSomeEvent().setEnabled(false);

/* perform some actions */

// and enable it again
getSomeEvent().setEnabled(true);

Moreover, you can toggle individual connections on and off (EventConnection instances), providing flexibility when working with events.此外,您可以切换单个连接的打开和关闭 (EventConnection实例),从而在处理事件时提供灵活性。

源代码 (C++)
EventConnection connection;
/* ... */

// disable the connection
connection.setEnabled(false);

/* perform some actions */

// and enable it back when necessary
connection.setEnabled(true);

Later, you can unsubscribe from the event via EventConnection as follows:稍后,您可以通过EventConnection取消订阅事件,如下所示:

注意
You cannot unsubscribe using the pointer to the handler function if the connection was created via EventConnection.如果连接是通过EventConnection创建的,则不能使用指向处理程序函数的指针取消订阅。
源代码 (C++)
void shutdown()
{
	// break the connection by using EventConnection
	connection.disconnect();
}

If a class handles the event, you can declare the EventConnection instance as a class member and use it for events subscription. In this case, all linked subscriptions will be automatically removed when the class destructor is called. For example:如果一个类处理该事件,您可以将EventConnection实例声明为类成员并将其用于事件订阅。 在这种情况下,当调用类析构函数时,所有链接的订阅将被自动删除。 例如:

源代码 (C++)
// a class handling the event
class SomeClass
{
public:

	// instance of the EventConnection class as a class member
	EventConnection connection;

	// an event handler implemented as a class member
	void on_event()
	{
		Log::message("\Handling the event\n");
	}
};

// create a class instance
SomeClass *obj = new SomeClass();

// connect the handler function with the event by using EventConnection;
// specify the class instance as the event handler belongs to the class
getSomeEvent().connect(obj->connection, obj, &SomeClass::on_event);

/* ... */

// the instance of the handler class is deleted with all its subscriptions;
// subscriptions are removed automatically in the destructor
delete obj;

Multiple Subscriptions with EventConnections
具有EventConnections的多个订阅#

The EventConnections class is a container for the EventConnection instances. Multiple subscriptions to a single event or different events can be linked to a single EventConnections instance. EventConnections 类是 EventConnection 实例的容器。 对单个事件或不同事件的多个订阅可以链接到单个EventConnections实例。

For example, you can create multiple subscriptions to a single event as follows:例如,您可以为单个事件创建多个订阅,如下所示:

源代码 (C++)
EventConnections connections;

// event handlers
static void on_some_event_0() { Log::message("\Handling the 1st event\n"); }
static void on_some_event_1() { Log::message("\Handling the 2nd event\n"); }

static void Main(string[] args)
{
	// add two handlers for the event
	// and link it to an EventConnections instance to remove a pack of subscriptions later
	getSomeEvent().connect(connections, this, on_some_event_0);
	getSomeEvent().connect(connections, this, on_some_event_1);
	
}

Also, you can create multiple subscriptions to different events:此外,您可以为不同的事件创建多个订阅:

源代码 (C++)
EventConnections connections;

// event handlers
static void on_some_event_0() { Log::message("\Handling the 1st event\n"); }
static void on_some_event_1() { Log::message("\Handling the 2nd event\n"); }
static void on_some_event_2() { Log::message("\Handling the 3rd event\n"); }

static void Main(string[] args)
{
	// subscribe for different events with handlers to be executed when the events are triggered;
	// here multiple subscriptions are linked to a single EventConnections class instance
	getSomeEvent0().connect(connections, this, on_some_event_0);
	getSomeEvent1().connect(connections, this, on_some_event_1);
	getSomeEvent2().connect(connections, this, on_some_event_2);
}

Later, you can unsubscribe from the events via EventConnections as follows:稍后,您可以通过EventConnections取消订阅事件,如下所示:

注意
You cannot unsubscribe by using the pointer to the handler function if the connection was created via EventConnections.如果连接是通过EventConnections创建的,则不能使用指向处理程序函数的指针来取消订阅。
源代码 (C++)
// break the connection by using EventConnections
// all instances of EventConnection will be removed from the EventConnections container
connections.disconnectAll();

If a class handles the event, you can declare the EventConnections instance as a class member and use it for events subscription. In this case, all linked subscriptions will be automatically removed when the class destructor is called. See the example provided above — the same applies to EventConnections.如果一个类处理该事件,您可以将EventConnections实例声明为类成员并将其用于事件订阅。 在这种情况下,当调用类析构函数时,所有链接的订阅将被自动删除。 请参阅上面提供的示例,这同样适用于EventConnections

Inheriting from EventConnections
从EventConnections继承#

There is another way to automatically unsubscribe from the event handled by a class: you can inherit it from EventConnections. In this case, the event will interact with the user class in the same way as with EventConnections. All linked subscriptions will be removed automatically in the user class destructor.还有另一种方法可以自动取消订阅由类处理的事件:您可以从EventConnections继承它。在这种情况下,事件将以与EventConnections相同的方式与用户类交互。所有链接订阅都将在用户类析构函数中自动删除。

源代码 (C++)
class UserClass : public EnventConnections
{
public:

	void init(Event<int, float> &event)
	{
		event.connect(this, &UserClass::on_event);
	}

	void on_event(int a, float b)
	{
		Log::message("\Handling the event\n");
	}
};

int main()
{
	UserClass *user_class = new UserClass();
	user_class->init(getSomeEvent());
	delete user_class; // my_class will automatically unsubscribe from all of the events in the destructor

	return 0;
}

Using Lambda Functions
使用Lambda函数#

You can pass a lambda function as an argument to the connect() function to handle the event: there is no need to perform internal type conversions. All features available for the handler functions are also applicable to lambda functions, except additional arguments.您可以将lambda函数作为参数传递给connect()函数来处理事件:不需要执行内部类型转换。处理程序函数可用的所有特性也适用于lambda函数,除了附加参数。

源代码 (C++)
int main()
{
	// EventConnections class instance to manage event subscriptions
	EventConnections connections;

	auto l = [](int a, float b) {};

	event.connect(connections, l);

	event.connect(connections, [](int a, float b) {});

	event.connect(connections, [](int a {}));

	return 0;
}

Connection Descriptors
连接描述符#

When subscribing to the event, a connection descriptor EventConnectionId is returned. You can save it and use it later to unsubscribe.订阅事件时,将返回连接描述符EventConnectionId。您可以保存它并在以后使用它来取消订阅。

注意
We do not recommend this approach. It is provided for informational purposes only.我们不推荐这种方法。本文仅供参考之用。
源代码 (C++)
// subscribe for the Contacts event with a lambda handler function and keeping connection ID
EventConnectionId contacts_handler_id = body->getEventContacts().connect([](const Ptr<Body> & body) { 
		Log::message("\Handling Contacts event (lambda).\n");
	}
);

// remove the subscription later using the ID
body->getEventContacts().disconnect(contacts_handler_id);

In some cases using a connection descriptor leads to a failure:在某些情况下,使用连接描述符会导致失败:

  • If you are subscribed to the event via EventConnection, it will become invalid when unsubscribing using the connection descriptor.如果您通过EventConnection订阅了该事件,那么在使用连接描述符取消订阅时,该事件将无效。
  • If you have multiple subscriptions linked to EventConnections, unsubscribing from a single event using the connection descriptor will not remove the EventConnection instance from the container.如果有多个订阅链接到EventConnections,那么使用连接描述符取消订阅单个事件不会从容器中删除EventConnection实例。

Direct Unsafe Subscription
直接不安全订阅#

You can subscribe to events directly via the connectUnsafe() function, without specifying an istance of the EventConnection/EventConnections class, and unsubscribe via disconnect():您可以直接通过 connectUnsafe() 函数订阅事件,而无需指定 EventConnection/EventConnections 类的实例,并通过 disconnect() 取消订阅:

  • The connectUnsafe() function is used to connect the event and the event handler. The number of function arguments may vary.connectUnsafe()函数用于连接事件和事件处理程序。函数参数的数量可能会改变。
  • The disconnect() function is used to break the connection between the event and its handler. It receives a pointer to the handler function or a connection descriptor as an argument.disconnect()函数用于断开事件与其处理程序之间的连接。它接收指向处理程序函数或连接描述符的指针作为参数。
源代码 (C++)
// a handler function
void on_event(int a, float b)
{
	Log::message("\Handling the event\n");
}

void init()
{
	// connect the handler function with the event directly
	getSomeEvent().connectUnsafe(on_event);
	
	// disconnect the handler function and the event by using the pointer to this function
	getSomeEvent().disconnect(on_event);

	// ...

	// direct connect using a lambda expression 
	// and keeping a connection descriptor to remove the subscription later
	EventConnectionId connection_id = event.connectUnsafe([](int a, float b) {});

	// disconnect the handler function and the event by using connection descriptor
	getSomeEvent().disconnect(connection_id);

	return 0;
}

If a class handles the event, you should pass the class instance as an argument to the connect() and disconnect() functions. For example:如果类处理事件,则应该将类实例作为参数传递给connect()disconnect()函数。例如:

源代码 (C++)
// a class handling the event
class SomeClass
{
public:

	// an event handler implemented as a class member
	void on_event()
	{
		Log::message("\Handling the event\n");
	}
};

// create a class instance
SomeClass *obj = new SomeClass();

// connect the handler function with the event;
// specify the class instance as the event handler belongs to the class
getSomeEvent().connectUnsafe(obj, &SomeClass::on_event);

/* ... */

// remove the subscription
getSomeEvent().disconnect(obj, &SomeClass::on_event);

Using Predefined Events
使用预定义事件#

Some Unigine API members have several predefined events that can be handled in specific cases. The following chapters showcase the practical use of the concepts described above.一些Unigine API成分有几个预定义的事件,可以在特定情况下处理。下面的章节展示了上述概念的实际应用。

Triggers
触发器#

Triggers are used to detect changes in nodes position or state. Unigine offers three types of built-in triggers:触发器用于检测节点位置或状态的变化。Unigine提供三种类型的内置触发器:

Here is a simple NodeTrigger usage example. The event handlers are set via pointers specified when subscribing to the following events: EventEnabled and EventPosition.下面是一个简单的NodeTrigger使用示例。事件处理程序是通过订阅以下事件时指定的指针来设置的: EventEnabledEventPosition

源代码 (C++)
#include <UnigineLogic.h>
#include <UnigineGame.h>

using namespace Unigine;

class AppWorldLogic : public Unigine::WorldLogic {

public:

	virtual int init();
	virtual int update();

	/*...*/

private:

	ObjectMeshStaticPtr object;
	NodeTriggerPtr trigger;

	// EventConnections class instance to manage event subscriptions
	EventConnections econnections;

	void position_event_handler(const NodeTriggerPtr &trigger)
	{
		Log::message("Object position has been changed. New position is: (%f %f %f)\n", trigger->getWorldPosition().x, trigger->getWorldPosition().y, trigger->getWorldPosition().z);
	}

	void enabled_event_handler(const NodeTriggerPtr &trigger)
	{
		Log::message("The enabled flag is %d\n", trigger->isEnabled());
	}
};
AppWorldLogic.cpp (C++)
#include "AppWorldLogic.h"

using namespace Math;

int AppWorldLogic::init() {

	// create a mesh
	object = ObjectMeshStatic::create("core/meshes/box.mesh");
	// change material albedo color
	object->setMaterialParameterFloat4("albedo_color", vec4(1.0f, 0.0f, 0.0f, 1.0f), 0);

	// create a trigger node
	trigger = NodeTrigger::create();

	// add the trigger node to the static mesh as a child node
	object->addWorldChild(trigger);

	// subscribe for the Enabled and Position events
	trigger->getEventEnabled().connect(econnections, this, &AppWorldLogic::enabled_event_handler);
	trigger->getEventPosition().connect(econnections, this, &AppWorldLogic::position_event_handler);

	return 1;
}

int AppWorldLogic::update()
{

	float time = Game::getTime();
	Vec3 pos = Vec3(Math::sin(time) * 2.0f, Math::cos(time) * 2.0f, 0.0f);
	object->setEnabled(pos.x > 0.0f || pos.y > 0.0f);
	object->setWorldPosition(pos);

	return 1;
}

And here is an example of WorldTrigger that demonstrates how to subscribe to the Enter and Leave events with a corresponding handler and keep this connection to unsubscribe later.下面是一个WorldTrigger的示例,演示了如何使用相应的处理程序订阅EnterLeave事件,并保持其连接,以便稍后退订。

源代码 (C++)
WorldTriggerPtr trigger;
EventConnections event_connections;

// implement the Enter event handler
void AppWorldLogic::enter_event_handler(const NodePtr &node)
{
	Log::message("\nA node named %s has entered the trigger\n", node->getName());
}

// implement the Leave event handler
void AppWorldLogic::leave_event_handler1(const NodePtr &node)
{
	Log::message("\nA node named %s has left the trigger\n", node->getName());
}

// implement an additional Leave event handler
void AppWorldLogic::leave_event_handler2(const NodePtr &node)
{
	Log::message("\nAdditional Leave event handler.\n");
}

int AppWorldLogic::init()
{

	// create a world trigger node
	trigger = WorldTrigger::create(Math::vec3(3.0f));

	// add the Enter event handler to be executed when a node enters the world trigger
	// and attaching it to EventConnections instance to remove a pack of subscriptions later
	trigger->getEventEnter().connect(event_connections, this, &AppWorldLogic::enter_event_handler);
	// adding two handlers for the Leave event to be executed when a node leaves the world trigger
	// and attaching it to the same EventConnections instance as well
	trigger->getEventLeave().connect(event_connections, this, &AppWorldLogic::leave_event_handler1);
	trigger->getEventLeave().connect(event_connections, this, &AppWorldLogic::leave_event_handler2);

	return 1;
}

To remove subscriptions to the events, use the following code:要取消订阅事件,请使用以下代码:

源代码 (C++)
// remove all subscriptions to the Leave and Enter events
event_connections.disconnectAll();

Widgets
小部件#

The widgets base class Widget allows subscribing to events.小部件基类Widget允许订阅事件。

The example below demonstrates how to subscribe for the widget's Clicked event.下面的示例演示了如何订阅小部件的Clicked事件。

AppWorldLogic.cpp

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

	return 1;
}

// EventConnections class instance to manage event subscriptions
EventConnections e_conn;

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->getEventClicked().connect(e_conn, this, &AppWorldLogic::onButtonClicked);
	// add the created button widget to the system GUI
	gui->addChild(widget_button, Gui::ALIGN_OVERLAP | Gui::ALIGN_FIXED);

	return 1;
}

Physics
物理#

You can track certain events of the physics-related Bodies and Joints:您可以跟踪物理相关的关节的某些事件:

The following code example shows how to subscribe to the Body events.下面的代码示例展示了如何订阅Body事件。

AppWorldLogic.cpp

源代码 (C++)
// set the node's albedo color to red on the freezing event
int AppWorldLogic::frozen_event_handler(const BodyPtr &body)
{
	body->getObject()->setMaterialParameterFloat4("albedo_color", Math::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_event_handler(const BodyPtr &body)
{
	body->getObject()->setMaterialParameterFloat4("albedo_color", Math::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_event_handler(const BodyPtr &body, int num)
{
	body->getObject()->setMaterialParameterFloat4("albedo_color", Math::vec4(1.0f, 1.0f, 0.0f, 1.0f), 0);

	return 1;
}

// EventConnections class instance to manage event subscriptions
EventConnections e_conn;

int AppWorldLogic::init()
{

	// create a box
	ObjectMeshStaticPtr meshStatic = ObjectMeshStatic::create("core/meshes/box.mesh");
	meshStatic->setPosition(Math::Vec3(0, 0, 5.0f));
	// add a rigid body to the box
	BodyRigidPtr body = BodyRigid::create(meshStatic);
	// subscribe for body events
	body->getEventFrozen().connect(e_conn, this, &AppWorldLogic::frozen_event_handler);
	body->getEventPosition().connect(e_conn, this, &AppWorldLogic::position_event_handler);
	body->getEventContactEnter().connect(e_conn, this, &AppWorldLogic::contact_enter_event_handler);
	// add a shape to the body
	ShapeBoxPtr shape = ShapeBox::create(body, Math::vec3(1.0f));

	return 1;
}
注意
Physics-based events are executed in the main thread, as they are mainly used for creation, destruction or modification of other objects.基于物理的事件在主线程中执行,因为它们主要用于创建、销毁或修改其他对象。

Properties
属性#

Events 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 events.事件可用于确定在添加或删除节点和表面属性以及交换节点属性时要执行的操作。下面是一个演示如何通过事件跟踪添加节点属性的示例。

AppWorldLogic.cpp

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

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

void AppWorldLogic::property_removed(const PropertyPtr &property)
{
	Log::message("Property \"%s\" was removed.\n", property->getName());
}

// EventConnections class instance to manage event subscriptions
EventConnections e_conn;

int AppWorldLogic::init()
{

	NodeDummyPtr node = NodeDummy::create();

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

	// subscribing to the PropertyNodeAdd event (adding a node property)
	node->getEventPropertyNodeAdd().connect(e_conn, this, &AppWorldLogic::node_property_added);

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

	// subscribing to the ParameterChanged event (changing property parameter)
	property->getEventParameterChanged().connect(e_conn, this, &AppWorldLogic::parameter_changed);

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

	// inherit a new property named "new_property_1" from the base property "surface_base"
	Properties::findManualProperty("surface_base")->inherit("new_property_1");

	// subscribing to property removal
	Properties::getEventRemoved().connect(e_conn, this, &AppWorldLogic::property_removed);

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

	return 1;
}
最新更新: 2024-12-13
Build: ()