Attempt at better managing lifecycle

This commit is contained in:
rodolpheh 2023-11-07 23:29:42 +00:00
parent 56c5ee15e0
commit 671f5cae12
4 changed files with 163 additions and 20 deletions

View File

@ -188,7 +188,6 @@ radius = 0.00197651
height = 0.0197651
[node name="RiggedHand" type="Node3D" node_paths=PackedStringArray("origin_hands", "rigged_hands", "spawner")]
process_mode = 4
script = ExtResource("1_58k8d")
origin_hands = NodePath("HandTracking/Debug/OriginHands")
rigged_hands = NodePath("Scene/XRToolsHands")
@ -856,6 +855,7 @@ update_mode = 1
[node name="HandTracking" type="Node3D" parent="."]
[node name="UltraleapHandTracking" type="UltraleapHandTracking" parent="HandTracking"]
startup_enable_images = false
script = ExtResource("1_r2upn")
[node name="UltraleapDeviceNode" type="UltraleapDeviceNode" parent="HandTracking"]

View File

@ -1,8 +1,4 @@
@tool
extends UltraleapHandTracking
func _ready():
start()
func on_tracking_mode_request(new_tracking_mode):
set_tracking_mode(new_tracking_mode)

View File

@ -26,12 +26,41 @@
using namespace godot;
UltraleapHandTracking::~UltraleapHandTracking() {
if (_isRunning) {
_isRunning = false;
UtilityFunctions::print("Destroying UltraleapHandTracking");
if (is_running) {
UtilityFunctions::print("Stopping the tracking thread");
keep_running = false;
messageLoop.join();
}
LeapCloseConnection(connectionHandle);
LeapDestroyConnection(connectionHandle);
dispose_ultraleap();
#if ANDROID_ENABLED
binder = NULL;
#endif
}
void UltraleapHandTracking::dispose_ultraleap() {
if (opened && connectionHandle) {
UtilityFunctions::print("Closing the connection");
LeapCloseConnection(connectionHandle);
opened = false;
}
if (connectionHandle) {
UtilityFunctions::print("Destroying the connection");
LeapDestroyConnection(connectionHandle);
connectionHandle = NULL;
}
#if ANDROID_ENABLED
if (binder != NULL) {
if (binder->call("IsBound")) {
binder->call("Unbind");
}
}
#endif
}
void UltraleapHandTracking::_bind_methods() {
@ -43,8 +72,10 @@ void UltraleapHandTracking::_bind_methods() {
);
ClassDB::bind_method(D_METHOD("start"), &UltraleapHandTracking::start);
ClassDB::bind_method(D_METHOD("stop"), &UltraleapHandTracking::stop);
ClassDB::bind_method(D_METHOD("is_connected"), &UltraleapHandTracking::is_connected);
ClassDB::bind_method(D_METHOD("is_started"), &UltraleapHandTracking::is_started);
ClassDB::bind_method(D_METHOD("set_last_frame", "last_frame"), &UltraleapHandTracking::set_last_frame);
ClassDB::bind_method(D_METHOD("get_last_frame"), &UltraleapHandTracking::get_last_frame);
@ -64,6 +95,12 @@ void UltraleapHandTracking::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_service_port", "service_port"), &UltraleapHandTracking::set_service_port);
ClassDB::bind_method(D_METHOD("get_service_port"), &UltraleapHandTracking::get_service_port);
ClassDB::bind_method(D_METHOD("set_autostart", "enable"), &UltraleapHandTracking::set_autostart);
ClassDB::bind_method(D_METHOD("get_autostart"), &UltraleapHandTracking::get_autostart);
ClassDB::bind_method(D_METHOD("set_enable_images", "enable"), &UltraleapHandTracking::set_enable_images);
ClassDB::bind_method(D_METHOD("get_enable_images"), &UltraleapHandTracking::get_enable_images);
ClassDB::bind_method(D_METHOD("set_images_policy", "value"), &UltraleapHandTracking::set_images_policy);
ClassDB::bind_method(D_METHOD("set_allow_pause_resume_policy", "value"), &UltraleapHandTracking::set_allow_pause_resume_policy);
@ -131,6 +168,32 @@ void UltraleapHandTracking::_bind_methods() {
"get_service_port"
);
ClassDB::add_property_group(
"UltraleapHandTracking",
"Startup",
"startup"
);
ClassDB::add_property(
"UltraleapHandTracking",
PropertyInfo(
Variant::BOOL,
"startup_autostart"
),
"set_autostart",
"get_autostart"
);
ClassDB::add_property(
"UltraleapHandTracking",
PropertyInfo(
Variant::BOOL,
"startup_enable_images"
),
"set_enable_images",
"get_enable_images"
);
// SIGNALS
ClassDB::add_signal(
@ -224,19 +287,32 @@ void UltraleapHandTracking::_bind_methods() {
}
void UltraleapHandTracking::start() {
if (started) {
UtilityFunctions::print("The tracking is already started");
return;
}
UtilityFunctions::print("Starting the tracking");
#ifdef ANDROID_ENABLED
if (Engine::get_singleton()->has_singleton("UltraleapBinder")) {
ALOGI("We'll try to use the binder");
Object* binder = Engine::get_singleton()->get_singleton("UltraleapBinder");
if (binder == NULL) {
ALOGI("Couldn't get the service binder, stopping");
return;
}
if (!binder->call("IsBound")) {
ALOGI("Binding to the service");
binder->call("Bind");
while (!binder->call("IsBound")) {
ALOGI("Not bound yet");
}
}
// This will freeze the app if the service doesn't bind
while (!binder->call("IsBound")) {
ALOGI("Not bound yet");
}
#endif
started = true;
LEAP_CONNECTION_CONFIG config;
// Set connection to multi-device aware
@ -248,14 +324,14 @@ void UltraleapHandTracking::start() {
if(connectionHandle || LeapCreateConnection(&config, &connectionHandle) == eLeapRS_Success) {
eLeapRS result = LeapOpenConnection(connectionHandle);
if(result == eLeapRS_Success) {
_isRunning = true;
opened = true;
{
LEAP_ALLOCATOR allocator = { allocate, deallocate, NULL };
LeapSetAllocator(connectionHandle, &allocator);
}
if (!Engine::get_singleton()->is_editor_hint()) {
if (!Engine::get_singleton()->is_editor_hint() && enable_images) {
LeapSetPolicyFlags(connectionHandle, eLeapPolicyFlag_Images, 0);
}
@ -265,6 +341,35 @@ void UltraleapHandTracking::start() {
}
}
void UltraleapHandTracking::stop() {
if (!started) {
UtilityFunctions::print("Tracking already stopped");
return;
}
UtilityFunctions::print("Trying to stop tracking...");
if (keep_running) {
UtilityFunctions::print("Turning off flag of thread");
keep_running = false;
}
// If the polling thread is still alive, we defer calling the stop function
// again on the next frame, and this until it's dead, then we will clean
// the connection
if (is_running) {
call_deferred("stop");
return;
}
messageLoop.join();
dispose_ultraleap();
started = false;
UtilityFunctions::print("Tracking stopped!");
}
void UltraleapHandTracking::handle_connection_event(const LEAP_CONNECTION_EVENT *evt) {
events.push({ "connection_status_changed", true });
connected = true;
@ -282,7 +387,10 @@ void UltraleapHandTracking::serviceMessageLoop() {
LEAP_CONNECTION_MESSAGE msg;
eLeapRS result;
while (_isRunning) {
keep_running = true;
is_running = true;
while (keep_running) {
result = LeapPollConnection(connectionHandle, 100, &msg);
if (result != eLeapRS_Success && result != eLeapRS_Timeout) {
@ -291,7 +399,7 @@ void UltraleapHandTracking::serviceMessageLoop() {
}
// Polling may have taken some time, re-check exit condition
if (!_isRunning) {
if (!keep_running) {
break;
}
@ -358,6 +466,8 @@ void UltraleapHandTracking::serviceMessageLoop() {
break;
}
}
is_running = false;
}
UltraleapTypes::TrackingMode UltraleapHandTracking::get_tracking_mode() {
@ -653,6 +763,7 @@ Ref<UltraleapDevice> UltraleapHandTracking::create_device(LEAP_DEVICE_REF ref) {
}
void UltraleapHandTracking::_notification(int p_what) {
//UtilityFunctions::print(p_what);
if (p_what == Node::NOTIFICATION_ENTER_TREE) {
set_process_internal(true);
}
@ -663,6 +774,19 @@ void UltraleapHandTracking::_notification(int p_what) {
events.pop();
}
}
else if (p_what == Node::NOTIFICATION_READY) {
#if ANDROID_ENABLED
// Get and store the binder
if (Engine::get_singleton()->has_singleton("UltraleapBinder")) {
binder = Engine::get_singleton()->get_singleton("UltraleapBinder");
}
#endif
// For now we will also start automatically if we're in the editor, so that we can have data for tool scripts
if (autostart || Engine::get_singleton()->is_editor_hint()) {
start();
}
}
}
String UltraleapHandTracking::generate_connection_payload() {

View File

@ -13,6 +13,7 @@
#include <LeapC.h>
#include <thread>
#include <queue>
#include <atomic>
#include "types.h"
#include "frame.h"
@ -29,6 +30,7 @@ public:
~UltraleapHandTracking();
void start();
void stop();
UltraleapTypes::TrackingMode default_tracking_mode = UltraleapTypes::TrackingMode::Desktop;
@ -46,6 +48,9 @@ public:
String service_ip = String("127.0.0.1");
uint32_t service_port = 12345;
bool autostart = true;
bool enable_images = true;
Variant get_last_frame();
void set_last_frame(Variant value) { return; }
@ -64,7 +69,14 @@ public:
Variant get_service_port() { return service_port; }
void set_service_port(Variant value) { service_port = value; }
Variant get_autostart() { return autostart; }
void set_autostart(Variant value) { autostart = value; }
Variant get_enable_images() { return enable_images; }
void set_enable_images(Variant value) { enable_images = value; }
bool is_connected() { return connected; }
bool is_started() { return started; }
// Policy setters
void set_images_policy(bool value);
@ -89,12 +101,18 @@ protected:
private:
bool _isRunning = false;
std::atomic<bool> is_running = false;
std::atomic<bool> keep_running = false;
LEAP_CONNECTION connectionHandle = NULL;
LEAP_CLOCK_REBASER clockSynchronizer;
std::thread messageLoop;
bool connected = false;
bool started = false; /* The whole thing is started */
bool opened = false; /* Indicate an opened connection */
bool connected = false; /* We have confirmed connection */
Ref<UltraleapDevice> primary_device = NULL;
@ -105,6 +123,7 @@ private:
std::queue<event> events;
void serviceMessageLoop();
void dispose_ultraleap();
void handle_tracking_event(const LEAP_TRACKING_EVENT* event, uint32_t device_id);
void handle_image_event(const LEAP_IMAGE_EVENT* event, uint32_t device_id);
@ -126,6 +145,10 @@ private:
Ref<UltraleapDevice> create_device(LEAP_DEVICE_REF ref);
uint32_t policy_flags = UINT32_MAX;
#ifdef ANDROID_ENABLED
Object *binder = NULL;
#endif
};
#endif